Re: [aur-dev] [PATCH 1/1] rename *.inc files to *.inc.php and adjust imports and references
On Tue, Jun 21, 2011 at 6:38 AM, Lukas Fleischer archli...@cryptocrack.de wrote: On Sun, May 29, 2011 at 02:33:37PM -0700, elij wrote: --- .gitignore | 1 + TRANSLATING | 2 +- web/README | 4 ++-- web/html/account.php | 4 ++-- web/html/addvote.php | 2 +- web/html/index.php | 4 ++-- web/html/logout.php | 4 ++-- web/html/packages.php | 8 web/html/passreset.php | 2 +- web/html/pkgsubmit.php | 6 +++--- web/html/rss.php | 2 +- web/html/tu.php | 2 +- web/html/voters.php | 4 ++-- web/lib/{acctfuncs.inc = acctfuncs.inc.php} | 0 web/lib/{aur.inc = aur.inc.php} | 8 web/lib/aurjson.class.php | 2 +- web/lib/{config.inc.proto = config.inc.php.proto} | 0 web/lib/{pkgfuncs.inc = pkgfuncs.inc.php} | 2 +- web/lib/{stats.inc = stats.inc.php} | 2 +- web/lib/{translator.inc = translator.inc.php} | 2 +- web/lib/{version.inc = version.inc.php} | 0 web/template/pkg_search_form.php | 2 +- web/template/template.phps | 4 ++-- 23 files changed, 34 insertions(+), 33 deletions(-) rename web/lib/{acctfuncs.inc = acctfuncs.inc.php} (100%) rename web/lib/{aur.inc = aur.inc.php} (99%) rename web/lib/{config.inc.proto = config.inc.php.proto} (100%) rename web/lib/{pkgfuncs.inc = pkgfuncs.inc.php} (99%) rename web/lib/{stats.inc = stats.inc.php} (98%) rename web/lib/{translator.inc = translator.inc.php} (97%) rename web/lib/{version.inc = version.inc.php} (100%) Basically looks good. You should also amend the merge message for 1.9.0 in UPGRADING and add some additional note on renaming web/lib/config.inc to web/lib/config.inc.php *before* the merge message. huh?
Re: [aur-dev] Output buffering and header() usage
On Tue, Jun 21, 2011 at 9:19 AM, Dan McGee dpmc...@gmail.com wrote: On Tue, Jun 21, 2011 at 11:11 AM, Lukas Fleischer archli...@cryptocrack.de wrote: Some possible solutions/workarounds that came into my mind: * Use javascript redirects instead. * Just buffer output everywhere (ob_start(), ob_flush()). * Rewrite package search to retrieve package search results before even printing out anything. Thoughts? I tend to prefer the latter, cause it seems to be the only clean way (and the MVC way) of doing this. Don't automatically redirect is actually what I just did. Not because archweb had the bug, but I was finding the behavior annoying, and at least in the case where a package may or may not be in testing, sometimes the redirect happens while other times it doesn't. However, if you are going to do anything, I'd say package search itself should be refactored off into some library code, and once you get the results back you can actually start thinking about what to do with them. I agree with Dan, and would like to additionally go on record as firmly against redirecting with javascript.
Re: [aur-dev] [PATCH 1/1] Make cache type selectable based on config value
On Tue, Jun 21, 2011 at 6:33 AM, Lukas Fleischer archli...@cryptocrack.de wrote: On Sun, May 29, 2011 at 04:27:55PM -0700, elij wrote: Provie a mechanism to specify cache type from NONE, APC, or MEMCACHE based on a config variable. If MEMCACHE type is selected, a list of servers can be specified to provide multiserver support. Note that php-memcaced is required for MEMCACHE support. Sorry for the late response, I was very busy recently. Did you actually test MEMCACHE support? I'm still too busy to setup and test less important stuff thoroughly but I trust your judgement, especially since this will probably be rarely used. It has been quite a while since I submitted the patch. I believe I tested it (why wouldn't I?), but I don't remember to the extent that I did so. --- web/lib/aur.inc.php | 49 +--- web/lib/cachefuncs.inc.php | 85 ++ web/lib/config.inc.php.proto | 10 + 3 files changed, 96 insertions(+), 48 deletions(-) create mode 100644 web/lib/cachefuncs.inc.php diff --git a/web/lib/aur.inc.php b/web/lib/aur.inc.php index 7cf43e6..e65677d 100644 --- a/web/lib/aur.inc.php +++ b/web/lib/aur.inc.php @@ -13,12 +13,7 @@ set_lang(); include_once(config.inc.php); include_once(version.inc.php); include_once(acctfuncs.inc.php); - -# Check if APC extension is loaded, and set cache prefix if it is -if (!defined('EXTENSION_LOADED_APC')) { - define('EXTENSION_LOADED_APC', extension_loaded('apc')); - define('APC_PREFIX', 'aur:'); -} +include_once(cachefuncs.inc.php); # see if the visitor is already logged in # @@ -263,48 +258,6 @@ function db_query($query=, $db_handle=) { return $result; } -# set a value in the cache (currently apc) if cache -# is available for use. if not available, this becomes -# effectively a no-op (return value is false) -# accepts an optional TTL (defaults to 600 seconds) -function set_cache_value($key, $value, $ttl=600) { - $status = false; - if (EXTENSION_LOADED_APC) { - $status = apc_store(APC_PREFIX.$key, $value, $ttl); - } - return $status; -} - -# get a value from the cache (currently apc) if cache -# is available for use. if not available, this -# returns false (optionally sets passed in variable $status -# to false, much like apc_fetch behaves). this allows -# for testing the fetch result appropriately even in the event -# that a 'false' value was the value in the cache. -function get_cache_value($key, $status=false) { - if(EXTENSION_LOADED_APC) { - $ret = apc_fetch(APC_PREFIX.$key, $status); - if ($status) { - return $ret; - } - } - return $status; -} - -# run a simple db query, retrieving and/or caching the value if APC -# is available for use -# accepts an optioanal TTL value (defaults to 600 seconds) -function db_cache_value($dbq, $dbh, $key, $ttl=600) { - $status = false; - $value = get_cache_value($key, $status); - if (!$status) { - $result = db_query($dbq, $dbh); - $row = mysql_fetch_row($result); - $value = $row[0]; - set_cache_value($key, $value, $ttl); - } - return $value; -} # set up the visitor's language # diff --git a/web/lib/cachefuncs.inc.php b/web/lib/cachefuncs.inc.php new file mode 100644 index 000..8e32370 --- /dev/null +++ b/web/lib/cachefuncs.inc.php @@ -0,0 +1,85 @@ +?php + +if (!defined('CACHE_TYPE')) { + define('CACHE_TYPE', 'NONE'); +} + +# Check if APC extension is loaded, and set cache prefix if it is +if (CACHE_TYPE == 'APC' !defined('EXTENSION_LOADED_APC')) { + define('EXTENSION_LOADED_APC', extension_loaded('apc')); + define('CACHE_PREFIX', 'aur:'); +} + +# Check if memcache extension is loaded, and set cache prefix if it is +if (CACHE_TYPE == 'MEMCACHE' !defined('EXTENSION_LOADED_MEMCACHE')) { + define('EXTENSION_LOADED_MEMCACHE', extension_loaded('memcached')); + define('CACHE_PREFIX', 'aur:'); + global $memcache; + $memcache = new Memcached(); + $mcs = defined('MEMCACHE_SERVERS') ? MEMCACHE_SERVERS : '127.0.0.1:11211'; + foreach (explode(',', $mcs) as $elem) { + $telem = trim($elem); + $mcserver = explode(':', $telem); + $memcache-addServer($mcserver[0], intval($mcserver[1])); + } +} + +# set a value in the cache (currently apc) if cache +# is available for use. if not available, this becomes +# effectively a no-op (return value is false) +# accepts an optional TTL (defaults to 600 seconds) +function set_cache_value($key, $value, $ttl=600) { + $status = false; + if (defined('EXTENSION_LOADED_APC')) { + $status = apc_store(CACHE_PREFIX.$key, $value, $ttl); + } + if (defined('EXTENSION_LOADED_MEMCACHE')) { + global $memcache
Re: [aur-dev] [PATCH 1/2] refactor apc code and move to aur.inc
On Sun, May 29, 2011 at 1:59 PM, elij elij...@gmail.com wrote: On Sun, May 29, 2011 at 7:27 AM, Lukas Fleischer archli...@cryptocrack.de wrote: On Sat, May 28, 2011 at 04:17:09PM -0700, elij wrote: + if(EXTENSION_LOADED_APC) { + $ret = apc_fetch(APC_PREFIX.$key, $status); + if ($status) { + return $ret; + } + } + return $status; +} I'd prefer to change get_cache_value()'s signature to return the status indicator and pass the actual result by reference. That way, it could be used as follows: if (get_cache_value('foo', $foo)) { do_something $foo } That just feels much more common and convenient. Any objections? That seems a bit unconventional, considering the existing codebase and common php practices. While it might make for the occasional nice conditional-if test, I think it is more of a leaky abstraction than the existing method. I made an attempt to match the api signature for apc_fetch and memcache::get, so that I had to change as little calling code as possible (while making the api somewhat expected). The version as written behaves like the existing apc_fetch: http://www.php.net/manual/en/function.apc-fetch.php And purposefully similarly to memcache::get (if no bool reference is passed in to get_cache_value): http://us.php.net/manual/en/memcache.get.php Memcache::get returns false on failure, which can be problematic if a falsey value was stored in memcache, and you were trying to get it out (and test that retrieval succeeded). Passing a bool by reference fixes that case. You _can_ use a convention like this: if(!($foo = get_cache_value('bar'))) { // do stuff } As get_cache_value on failure *also* returns a falsey value, but this runs into the memcache api problem of what happens if you want to retrieve a falsey value. If you know that either you never store a falsey value for that key, or if your conditional test is appropriate assuming a falsey value stored (eg. if the condition is false due to failure or retrieval of a falseyness, the expected behavior is the same), then that convention works fine. Passing a data container by reference (your suggestion) would also work fine, but I don't see that very often in practice. I am probably not very current on php conventions though, and I am using the php documentation as a reference for 'best practices for api signatures'. Which may be a fools errand to some extent. ;) Do you make use of the 'pass data container by reference' convention regularly, or see it commonly used? function updates_table($dbh) { - global $apc_prefix, $apc_ttl; - $key = $apc_prefix . 'recent_updates'; - if(!(EXTENSION_LOADED_APC ($newest_packages = apc_fetch($key { + $key = 'recent_updates'; + if(!($newest_packages = get_cache_value($key))) { Any reason to use an additional variable for the key here? Nope. That was just how it was, and I missed changing it to inline. Note the diff. Actually, I just looked at the file, and the key is used twice (slightly later in the same function). At the time I probably thought it was better to have a variable than multiple instances of the same string. $q = 'SELECT * FROM Packages ORDER BY ModifiedTS DESC LIMIT 10'; $result = db_query($q, $dbh); @@ -43,26 +13,23 @@ function updates_table($dbh) while ($row = mysql_fetch_assoc($result)) { $newest_packages-append($row); } - if (EXTENSION_LOADED_APC) { - apc_store($key, $newest_packages, $apc_ttl); - } + set_cache_value($key, $newest_packages); Looks like you introduced a whitespace mistake here. Ah yes. I have vim set to use tabs on php files, but the inc files do not end in php... :/ Which as an aside is not a good practice. If for some reason there was a server configuration error, the inc files would be served up as plain text. It is best practice to have config files (such as config.inc) end in .php so they will be rendered in the off chance the file is exposed. The include files should probably be renamed. I can fix this one line of whitespace and resubmit if desired.
[aur-dev] [PATCH 1/1] rename *.inc files to *.inc.php and adjust imports and references
--- .gitignore |1 + TRANSLATING|2 +- web/README |4 ++-- web/html/account.php |4 ++-- web/html/addvote.php |2 +- web/html/index.php |4 ++-- web/html/logout.php|4 ++-- web/html/packages.php |8 web/html/passreset.php |2 +- web/html/pkgsubmit.php |6 +++--- web/html/rss.php |2 +- web/html/tu.php|2 +- web/html/voters.php|4 ++-- web/lib/{acctfuncs.inc = acctfuncs.inc.php} |0 web/lib/{aur.inc = aur.inc.php} |8 web/lib/aurjson.class.php |2 +- web/lib/{config.inc.proto = config.inc.php.proto} |0 web/lib/{pkgfuncs.inc = pkgfuncs.inc.php} |2 +- web/lib/{stats.inc = stats.inc.php} |2 +- web/lib/{translator.inc = translator.inc.php} |2 +- web/lib/{version.inc = version.inc.php} |0 web/template/pkg_search_form.php |2 +- web/template/template.phps |4 ++-- 23 files changed, 34 insertions(+), 33 deletions(-) rename web/lib/{acctfuncs.inc = acctfuncs.inc.php} (100%) rename web/lib/{aur.inc = aur.inc.php} (99%) rename web/lib/{config.inc.proto = config.inc.php.proto} (100%) rename web/lib/{pkgfuncs.inc = pkgfuncs.inc.php} (99%) rename web/lib/{stats.inc = stats.inc.php} (98%) rename web/lib/{translator.inc = translator.inc.php} (97%) rename web/lib/{version.inc = version.inc.php} (100%) diff --git a/.gitignore b/.gitignore index b1fb977..11e9b7e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ robots.txt *.swp web/lib/config.inc +web/lib/config.inc.php *.DS_Store web/html/xml/*.xml dummy-data.sql* diff --git a/TRANSLATING b/TRANSLATING index 56b3383..d8f1bd4 100644 --- a/TRANSLATING +++ b/TRANSLATING @@ -38,7 +38,7 @@ $ msginit -l locale -o locale.po -i aur.pot $ poedit locale.po 5. If you have a working AUR setup, add a line for the new translation in - web/lib/config.inc.proto and test if everything looks right. + web/lib/config.inc.php.proto and test if everything looks right. 6. Upload the newly created .po file to Transifex. If you don't like the web interface, you can also use transifex-client to do that (see below). diff --git a/web/README b/web/README index 9bd3ecb..b8d1b72 100644 --- a/web/README +++ b/web/README @@ -97,9 +97,9 @@ Setup on Arch Linux: can insert garbage addresses with: mysql UPDATE Users SET Email = RAND() * RAND(); -7) Copy the config.inc.proto file to config.inc. Modify as needed. +7) Copy the config.inc.php.proto file to config.inc.php. Modify as needed. # cd ~/aur/web/lib/ - # cp config.inc.proto config.inc + # cp config.inc.php.proto config.inc.php 8) Point your browser to http://aur diff --git a/web/html/account.php b/web/html/account.php index afb0d7c..ca05d1a 100644 --- a/web/html/account.php +++ b/web/html/account.php @@ -2,8 +2,8 @@ set_include_path(get_include_path() . PATH_SEPARATOR . '../lib'); -include_once('aur.inc'); # access AUR common functions -include_once('acctfuncs.inc'); # access Account specific functions +include_once('aur.inc.php'); # access AUR common functions +include_once('acctfuncs.inc.php'); # access Account specific functions set_lang(); # this sets up the visitor's language check_sid();# see if they're still logged in diff --git a/web/html/addvote.php b/web/html/addvote.php index a459610..fe3037d 100644 --- a/web/html/addvote.php +++ b/web/html/addvote.php @@ -2,7 +2,7 @@ set_include_path(get_include_path() . PATH_SEPARATOR . '../lib'); -include_once(aur.inc); +include_once(aur.inc.php); set_lang(); check_sid(); html_header(); diff --git a/web/html/index.php b/web/html/index.php index 33c39eb..ffc5f00 100644 --- a/web/html/index.php +++ b/web/html/index.php @@ -2,11 +2,11 @@ set_include_path(get_include_path() . PATH_SEPARATOR . '../lib'); -include_once(aur.inc); +include_once(aur.inc.php); set_lang(); check_sid(); -include_once('stats.inc'); +include_once('stats.inc.php'); html_header( __(Home) ); diff --git a/web/html/logout.php b/web/html/logout.php index 95cf460..dee6456 100644 --- a/web/html/logout.php +++ b/web/html/logout.php @@ -2,8 +2,8 @@ set_include_path(get_include_path() . PATH_SEPARATOR . '../lib'); -include_once(aur.inc); # access AUR common functions -include_once(acctfuncs.inc); # access AUR common functions +include_once(aur.inc.php); # access AUR common functions +include_once(acctfuncs.inc.php);
[aur-dev] [PATCH 1/1] Make cache type selectable based on config value
Provie a mechanism to specify cache type from NONE, APC, or MEMCACHE based on a config variable. If MEMCACHE type is selected, a list of servers can be specified to provide multiserver support. Note that php-memcaced is required for MEMCACHE support. --- web/lib/aur.inc.php | 49 +--- web/lib/cachefuncs.inc.php | 85 ++ web/lib/config.inc.php.proto | 10 + 3 files changed, 96 insertions(+), 48 deletions(-) create mode 100644 web/lib/cachefuncs.inc.php diff --git a/web/lib/aur.inc.php b/web/lib/aur.inc.php index 7cf43e6..e65677d 100644 --- a/web/lib/aur.inc.php +++ b/web/lib/aur.inc.php @@ -13,12 +13,7 @@ set_lang(); include_once(config.inc.php); include_once(version.inc.php); include_once(acctfuncs.inc.php); - -# Check if APC extension is loaded, and set cache prefix if it is -if (!defined('EXTENSION_LOADED_APC')) { - define('EXTENSION_LOADED_APC', extension_loaded('apc')); - define('APC_PREFIX', 'aur:'); -} +include_once(cachefuncs.inc.php); # see if the visitor is already logged in # @@ -263,48 +258,6 @@ function db_query($query=, $db_handle=) { return $result; } -# set a value in the cache (currently apc) if cache -# is available for use. if not available, this becomes -# effectively a no-op (return value is false) -# accepts an optional TTL (defaults to 600 seconds) -function set_cache_value($key, $value, $ttl=600) { - $status = false; - if (EXTENSION_LOADED_APC) { - $status = apc_store(APC_PREFIX.$key, $value, $ttl); - } - return $status; -} - -# get a value from the cache (currently apc) if cache -# is available for use. if not available, this -# returns false (optionally sets passed in variable $status -# to false, much like apc_fetch behaves). this allows -# for testing the fetch result appropriately even in the event -# that a 'false' value was the value in the cache. -function get_cache_value($key, $status=false) { - if(EXTENSION_LOADED_APC) { - $ret = apc_fetch(APC_PREFIX.$key, $status); - if ($status) { - return $ret; - } - } - return $status; -} - -# run a simple db query, retrieving and/or caching the value if APC -# is available for use -# accepts an optioanal TTL value (defaults to 600 seconds) -function db_cache_value($dbq, $dbh, $key, $ttl=600) { - $status = false; - $value = get_cache_value($key, $status); - if (!$status) { - $result = db_query($dbq, $dbh); - $row = mysql_fetch_row($result); - $value = $row[0]; - set_cache_value($key, $value, $ttl); - } - return $value; -} # set up the visitor's language # diff --git a/web/lib/cachefuncs.inc.php b/web/lib/cachefuncs.inc.php new file mode 100644 index 000..8e32370 --- /dev/null +++ b/web/lib/cachefuncs.inc.php @@ -0,0 +1,85 @@ +?php + +if (!defined('CACHE_TYPE')) { + define('CACHE_TYPE', 'NONE'); +} + +# Check if APC extension is loaded, and set cache prefix if it is +if (CACHE_TYPE == 'APC' !defined('EXTENSION_LOADED_APC')) { + define('EXTENSION_LOADED_APC', extension_loaded('apc')); + define('CACHE_PREFIX', 'aur:'); +} + +# Check if memcache extension is loaded, and set cache prefix if it is +if (CACHE_TYPE == 'MEMCACHE' !defined('EXTENSION_LOADED_MEMCACHE')) { + define('EXTENSION_LOADED_MEMCACHE', extension_loaded('memcached')); + define('CACHE_PREFIX', 'aur:'); + global $memcache; + $memcache = new Memcached(); + $mcs = defined('MEMCACHE_SERVERS') ? MEMCACHE_SERVERS : '127.0.0.1:11211'; + foreach (explode(',', $mcs) as $elem) { + $telem = trim($elem); + $mcserver = explode(':', $telem); + $memcache-addServer($mcserver[0], intval($mcserver[1])); + } +} + +# set a value in the cache (currently apc) if cache +# is available for use. if not available, this becomes +# effectively a no-op (return value is false) +# accepts an optional TTL (defaults to 600 seconds) +function set_cache_value($key, $value, $ttl=600) { + $status = false; + if (defined('EXTENSION_LOADED_APC')) { + $status = apc_store(CACHE_PREFIX.$key, $value, $ttl); + } + if (defined('EXTENSION_LOADED_MEMCACHE')) { + global $memcache; + $status = $memcache-set(CACHE_PREFIX.$key, $value, $ttl); + } + return $status; +} + +# get a value from the cache (currently apc) if cache +# is available for use. if not available, this +# returns false (optionally sets passed in variable $status +# to false, much like apc_fetch behaves). this allows +# for testing the fetch result appropriately even in the event +# that a 'false' value was the value in the cache. +function get_cache_value($key, $status=false) { + if(defined('EXTENSION_LOADED_APC')) { + $ret =
[aur-dev] [PATCH 1/1] restructure the html/rpc.php endpoint
- move request_method test to the top, and catch other request types (HEAD, PUT, etc) - change how html output is handled. instead of building a string, just output the html - set appropriate response header for incorrect request_method. --- web/html/rpc.php | 60 - 1 files changed, 32 insertions(+), 28 deletions(-) diff --git a/web/html/rpc.php b/web/html/rpc.php index 1a9ca34..27439db 100644 --- a/web/html/rpc.php +++ b/web/html/rpc.php @@ -1,36 +1,40 @@ ?php - set_include_path(get_include_path() . PATH_SEPARATOR . '../lib'); - include_once(aurjson.class.php); -if ( $_SERVER['REQUEST_METHOD'] == 'GET' ) { -if ( isset($_GET['type']) ) { -$rpc_o = new AurJSON(); -echo $rpc_o-handle($_GET); -} -else { -// dump a simple usage output for people to use. -// this could be moved to an api doc in the future, or generated from -// the AurJSON class directly with phpdoc. For now though, just putting it here. -echo 'htmlbody'; -echo 'The methods currently allowed are: br /'; -echo 'ul'; -echo 'lisearch/li'; -echo 'liinfo/li'; -echo 'limultiinfo/li'; -echo 'limsearch/li'; -echo '/ulbr /'; -echo 'Each method requires the following HTTP GET syntax:br /'; -echo 'nbsp;nbsp; type=imethodname/iarg=idata/i br /br /'; -echo 'Where imethodname/i is the name of an allowed method, and idata/i is the argument to the call.br /'; -echo 'br /'; -echo 'If you need jsonp type callback specification, you can provide an additional variable icallback/i.br /'; -echo 'Example URL: br /nbsp;nbsp; http://aur-url/rpc.php?type=searcharg=foobarcallback=jsonp1192244621103'; -echo '/body/html'; -} +if ( $_SERVER['REQUEST_METHOD'] != 'GET' ) { + header('HTTP/1.1 405 Method Not Allowed'); +} + +if ( isset($_GET['type']) ) { + $rpc_o = new AurJSON(); + echo $rpc_o-handle($_GET); } else { -echo 'POST NOT SUPPORTED'; + // dump a simple usage output for people to use. + // this could be moved to an api doc in the future, or generated from + // the AurJSON class directly with phpdoc. For now though, just putting it + // here. +? +htmlbody +The methods currently allowed are: br / +ul + lisearch/li + liinfo/li + limultiinfo/li + limsearch/li +/ul br / +Each method requires the following HTTP GET syntax: br / +nbsp;nbsp; type=imethodname/iarg=idata/i +br /br / +Where imethodname/i is the name of an allowed method, and idata/i is the argument to the call. +br /br / +If you need jsonp type callback specification, you can provide an additional variable icallback/i. +br / +Example URL: br / + nbsp;nbsp; http://aur-url/rpc.php?type=searcharg=foobarcallback=jsonp1192244621103 +/body/html +?php +// close if statement } ? -- 1.7.2.5
[aur-dev] [PATCH 1/1] fix two issues (php notice level) with html/rss.php
- Undefined index: HTTPS in rss.php on line 8 - Undefined property: RSSCreator20::$cssStyleSheet in feedcreator.class.php on line 591 --- web/html/rss.php |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/web/html/rss.php b/web/html/rss.php index 0547815..d0a202b 100644 --- a/web/html/rss.php +++ b/web/html/rss.php @@ -5,10 +5,12 @@ include_once(aur.inc); include_once(feedcreator.class.php); #detect prefix -$protocol = $_SERVER[HTTPS]=='on' ? https : http; +$protocol = isset($_SERVER[HTTPS]) $_SERVER[HTTPS]=='on' ? https : http; $host = $_SERVER['HTTP_HOST']; $rss = new RSSCreator20(); +$rss-cssStyleSheet = false; +$rss-xslStyleSheet = false; # Use UTF-8 (fixes FS#10706). $rss-encoding = UTF-8; -- 1.7.2.5
[aur-dev] refactor apc cache code (centralize and genericize)
The first patch is a slight refactor and move of the apc cache code, out of stats.inc into aur.inc. This is to make it available for other code to utilize if desired. I made it a bit more generic, so other referncing code does not have to supply a cache prefix. It will apply a prefix on behalf of the calling cache_set code, and utilize the prefix on cache_get code. The second patch changes rss.php to use the apc cache, instead of a file based cache.
[aur-dev] [PATCH 1/2] refactor apc code and move to aur.inc
- move apc cache code to aur.inc (centralize) - refactor the apc usage in stats.inc to utilize new code in aur.inc --- web/lib/aur.inc | 49 ++ web/lib/stats.inc | 61 +++- 2 files changed, 62 insertions(+), 48 deletions(-) diff --git a/web/lib/aur.inc b/web/lib/aur.inc index fb267af..2b78c99 100644 --- a/web/lib/aur.inc +++ b/web/lib/aur.inc @@ -14,6 +14,12 @@ include_once(config.inc); include_once(version.inc); include_once(acctfuncs.inc); +# Check if APC extension is loaded, and set cache prefix if it is +if (!defined('EXTENSION_LOADED_APC')) { +define('EXTENSION_LOADED_APC', extension_loaded('apc')); +define('APC_PREFIX', 'aur:'); +} + # see if the visitor is already logged in # function check_sid() { @@ -257,6 +263,49 @@ function db_query($query=, $db_handle=) { return $result; } +# set a value in the cache (currently apc) if cache +# is available for use. if not available, this becomes +# effectively a no-op (return value is false) +# accepts an optional TTL (defaults to 600 seconds) +function set_cache_value($key, $value, $ttl=600) { +$status = false; +if (EXTENSION_LOADED_APC) { +$status = apc_store(APC_PREFIX.$key, $value, $ttl); +} +return $status; +} + +# get a value from the cache (currently apc) if cache +# is available for use. if not available, this +# returns false (optionally sets passed in variable $status +# to false, much like apc_fetch behaves). this allows +# for testing the fetch result appropriately even in the event +# that a 'false' value was the value in the cache. +function get_cache_value($key, $status=false) { +if(EXTENSION_LOADED_APC) { +$ret = apc_fetch(APC_PREFIX.$key, $status); +if ($status) { +return $ret; +} +} +return $status; +} + +# run a simple db query, retrieving and/or caching the value if APC +# is available for use +# accepts an optioanal TTL value (defaults to 600 seconds) +function db_cache_value($dbq, $dbh, $key, $ttl=600) { +$status = false; +$value = get_cache_value($key, $status); +if (!$status) { +$result = db_query($dbq, $dbh); +$row = mysql_fetch_row($result); +$value = $row[0]; +set_cache_value($key, $value, $ttl); +} +return $value; +} + # set up the visitor's language # function set_lang() { diff --git a/web/lib/stats.inc b/web/lib/stats.inc index 756fa27..29ba0bb 100644 --- a/web/lib/stats.inc +++ b/web/lib/stats.inc @@ -2,40 +2,10 @@ include_once('aur.inc'); -# APC configuration variables -$apc_prefix = 'aur:'; -$apc_ttl = 600; - -# Check if APC extension is loaded -if (!defined('EXTENSION_LOADED_APC')) - define('EXTENSION_LOADED_APC', extension_loaded('apc')); - -# run a simple db query, retrieving and/or caching the value if APC -# is available for use -# -function db_cache_value($dbq, $dbh, $key) -{ - global $apc_ttl; - $bool = false; - if(EXTENSION_LOADED_APC) { - $ret = apc_fetch($key, $bool); - } - if(!$bool) { - $result = db_query($dbq, $dbh); - $row = mysql_fetch_row($result); - $ret = $row[0]; - if (EXTENSION_LOADED_APC) { - apc_store($key, $ret, $apc_ttl); - } - } - return $ret; -} - function updates_table($dbh) { - global $apc_prefix, $apc_ttl; - $key = $apc_prefix . 'recent_updates'; - if(!(EXTENSION_LOADED_APC ($newest_packages = apc_fetch($key { + $key = 'recent_updates'; + if(!($newest_packages = get_cache_value($key))) { $q = 'SELECT * FROM Packages ORDER BY ModifiedTS DESC LIMIT 10'; $result = db_query($q, $dbh); @@ -43,26 +13,23 @@ function updates_table($dbh) while ($row = mysql_fetch_assoc($result)) { $newest_packages-append($row); } - if (EXTENSION_LOADED_APC) { - apc_store($key, $newest_packages, $apc_ttl); - } +set_cache_value($key, $newest_packages); } include('stats/updates_table.php'); } function user_table($user, $dbh) { - global $apc_prefix; $escuser = mysql_real_escape_string($user); $base_q = SELECT count(*) FROM Packages,Users WHERE Packages.MaintainerUID = Users.ID AND Users.Username=' . $escuser . '; $maintainer_unsupported_count = db_cache_value($base_q, $dbh, - $apc_prefix . 'user_unsupported_count:' . $escuser); + 'user_unsupported_count:' . $escuser); $q = SELECT count(*) FROM Packages,Users WHERE Packages.OutOfDateTS IS NOT NULL AND Packages.MaintainerUID = Users.ID AND Users.Username=' . $escuser . '; $flagged_outdated = db_cache_value($q, $dbh, - $apc_prefix . 'user_flagged_outdated:' . $escuser); +
Re: [aur-dev] [PATCH 1/1] add support for etag and conditional get (if-none-match)
On Sun, May 15, 2011 at 12:19 PM, Lukas Fleischer archli...@cryptocrack.de wrote: On Fri, May 13, 2011 at 12:55:40PM -0700, elij wrote: Add etag and if-none-match conditional get support. This will allow 'smart client' to save network bandwidth, as they can save the etag hash value for queries and test it later. Still an http request because this patch specifically sets a cache lifetime of zero, and must-revalidate. The benefit here is bandwidth savings. Caching based on expires headers would likely be counter productive, as the api data can change rather quickly...but etag is a nice compromise, and could be quite beneficial for bandwidth recution in some scenarios. --- web/lib/aurjson.class.php | 30 +- 1 files changed, 29 insertions(+), 1 deletions(-) I kinda like that one although I'm not really sure if this kind of caching is convenient enough here... Having a bit more detailed look at the single query methods: * search, msearch: Probably won't be repeated on a single client very often (repeated meaning doing the same search query more than once). * info: Gain will probably be low as the query results are very small. * multiinfo: Query results will change quite often, while the actual diffs will be small in most cases. Some delta based stuff may be more effective here but that will probably be overkill. ETags seem to be a good compromise, yeah :) Yeah. I see a couple of instances that would benefit from it. 1) Direct browser viewing of api urls. Developers or end users entering query strings manually. 2) My live-search implementation (and similar type apps) _should_ work better, as back and forward button (or identical search terms) should be cached client side by the browser. 3) A cli client could be modified to cache data, but I imagine the benefits here would be small, as I don't believe end users would repeat many queries in a short enough timeframe (before some data changes) to get much benefit from caching. Who knows though. heh 4) Could be a benefit for large groups of clients behind a cache proxy. 5) Could be a benefit if the arch server admins ever decided to throw varnish in front of the aur (or just the api).
Re: [aur-dev] [PATCH 1/4] remove submitter from package data
On Wed, May 11, 2011 at 7:11 AM, Lukas Fleischer archli...@cryptocrack.de wrote: On Tue, May 10, 2011 at 09:01:27PM -0700, elij wrote: --- web/html/pkgsubmit.php | 3 +-- web/lib/pkgfuncs.inc | 10 +- web/template/pkg_details.php | 11 --- 3 files changed, 2 insertions(+), 22 deletions(-) The submitter field proved to be useful in some cases where a package was moved from the official repos to the AUR and either turned out to be incomplete or wasn't properly removed from the official repos. I guess I don't see what benefit the submitter field would have in such an instance. If someone moved it from the official repos to the aur, would they not be the submitter and also the maintainer? What's the motivation of removing this one? There was a discussion in another thread about adding submitter to the api return results, and I mentioned that I felt that submitter field wasn't very relevant or useful. This patch stemmed from that discussion.
Re: [aur-dev] [PATCH 3/4] fix case where user does not exist
On Wed, May 11, 2011 at 7:22 AM, Lukas Fleischer archli...@cryptocrack.de wrote: On Tue, May 10, 2011 at 09:01:29PM -0700, elij wrote: the query was being performed when $id was not set, resulting in an invalid sql query being performed. --- web/lib/acctfuncs.inc | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/web/lib/acctfuncs.inc b/web/lib/acctfuncs.inc index 5bcff8b..b2f0548 100644 --- a/web/lib/acctfuncs.inc +++ b/web/lib/acctfuncs.inc @@ -786,6 +786,9 @@ function valid_passwd( $userID, $passwd ) */ function user_suspended( $id ) { + if (!$id) { + return false; + } $dbh = db_connect(); $q = SELECT Suspended FROM Users WHERE ID = . $id; $result = db_query($q, $dbh); Looks ok, but I'd rather say we should locate the code path that led to the unset parameter and add some additional validation there to avoid further unexpected behaviour. The source is in try_login (also in lib/acctfuncs.inc): if ( isset($_REQUEST['user']) || isset($_REQUEST['passwd']) ) { $userID = valid_user($_REQUEST['user']); if ( user_suspended( $userID ) ) { $login_error = Account Suspended.; } valid_user (also in the same file) can return (no value) in some cases. that large if/elseif block in try_login could probably have some more conditions added to test for existence of $userID before calling user_suspended on it. Still.. it might make sense to have a guard (the test added with this patch) in the function itself in case usage of it down the road changes (another code path or something).
Re: [aur-dev] [PATCH 1/4] remove submitter from package data
On Wed, May 11, 2011 at 11:51 AM, Dan McGee dpmc...@gmail.com wrote: On Wed, May 11, 2011 at 1:48 PM, elij elij...@gmail.com wrote: On Wed, May 11, 2011 at 7:11 AM, Lukas Fleischer archli...@cryptocrack.de wrote: On Tue, May 10, 2011 at 09:01:27PM -0700, elij wrote: --- web/html/pkgsubmit.php | 3 +-- web/lib/pkgfuncs.inc | 10 +- web/template/pkg_details.php | 11 --- 3 files changed, 2 insertions(+), 22 deletions(-) The submitter field proved to be useful in some cases where a package was moved from the official repos to the AUR and either turned out to be incomplete or wasn't properly removed from the official repos. I guess I don't see what benefit the submitter field would have in such an instance. If someone moved it from the official repos to the aur, would they not be the submitter and also the maintainer? Initially, yes. And then we all usually orphan the junk because we don't want it, we just put it there for postarity, so you've immediately lost information. I think it has a lot less usefulness on the web page itself (at least for the general public), so I wouldn't be against culling it there, but as far as a point of reference when trying to look at the packages, it makes since to keep around. It can be far different than what the maintainer field tells you. Hmm. So keeping it but maybe only showing it to TU or Developer class users may be more appropriate. Alternatively, it almost sounds like maintainer and submitter could be merged into an 'owner' value, and track owner history somehow (record each change of ownership in a join table). That might add the ability to track users that upload lots of packages, then disown them too. And track packages with high owner turnover (may tell whether a package is painful or burdensome to maintain). If such a thing were implemented though, I think it should be displayed only to TU or Developer class users. I can't see general users finding much use for it, but I could be wrong.
[aur-dev] [PATCH 2/4] test return value from db_query before assuming it is valid
make the sql query form consistent in usage by cleaning up instances where db_query's result was not inspected before attempting to fetch row data from the handle --- web/html/addvote.php | 16 +- web/html/tu.php | 17 +-- web/lib/acctfuncs.inc | 59 web/lib/aur.inc |8 - web/lib/pkgfuncs.inc | 43 +- web/template/actions_form.php | 52 web/template/tu_list.php |8 +- 7 files changed, 135 insertions(+), 68 deletions(-) diff --git a/web/html/addvote.php b/web/html/addvote.php index 5936d56..a459610 100644 --- a/web/html/addvote.php +++ b/web/html/addvote.php @@ -21,14 +21,26 @@ if ($atype == Trusted User OR $atype == Developer) { if (!empty($_POST['user'])) { $qcheck = SELECT * FROM Users WHERE Username = ' . mysql_real_escape_string($_POST['user']) . '; - $check = mysql_num_rows(db_query($qcheck, $dbh)); + $result = db_query($qcheck, $dbh); + if ($result) { + $check = mysql_num_rows($result); + } + else { + $check = 0; + } if ($check == 0) { $error.= __(Username does not exist.); } else { $qcheck = SELECT * FROM TU_VoteInfo WHERE User = ' . mysql_real_escape_string($_POST['user']) . '; $qcheck.= AND End UNIX_TIMESTAMP(); - $check = mysql_num_rows(db_query($qcheck, $dbh)); + $result = db_query($qcheck, $dbh); + if ($result) { + $check = mysql_num_rows($result); + } + else { + $check = 0; + } if ($check != 0) { $error.= __(%s already has proposal running for them., htmlentities($_POST['user'])); diff --git a/web/html/tu.php b/web/html/tu.php index c5cc36b..6ab8ae9 100644 --- a/web/html/tu.php +++ b/web/html/tu.php @@ -36,7 +36,13 @@ if ($atype == Trusted User OR $atype == Developer) { $qvoted = SELECT * FROM TU_Votes WHERE ; $qvoted.= VoteID = . $row['ID'] . AND ; $qvoted.= UserID = . uid_from_sid($_COOKIE[AURSID]); - $hasvoted = mysql_num_rows(db_query($qvoted, $dbh)); + $result = db_query($qvoted, $dbh); + if ($result) { + $hasvoted = mysql_num_rows($result); + } + else { + $hasvoted = 0; + } # List voters of a proposal. $qwhoVoted = SELECT tv.UserID,U.Username @@ -85,10 +91,15 @@ if ($atype == Trusted User OR $atype == Developer) { $canvote = 0; $errorvote = __(You've already voted for this proposal.); # Update if they voted - $hasvoted = mysql_num_rows(db_query($qvoted, $dbh)); + $result = db_query($qvoted, $dbh); + if ($result) { + $hasvoted = mysql_num_rows($result); + } $results = db_query($q, $dbh); - $row = mysql_fetch_assoc($results); + if ($results) { + $row = mysql_fetch_assoc($results); + } } } include(tu_details.php); diff --git a/web/lib/acctfuncs.inc b/web/lib/acctfuncs.inc index 8ffa2f7..5bcff8b 100644 --- a/web/lib/acctfuncs.inc +++ b/web/lib/acctfuncs.inc @@ -197,7 +197,7 @@ function process_account_form($UTYPE,$TYPE,$A,$U=,$T=,$S=,$E=, } if (!$error !valid_username($U) !user_is_privileged($editor_user)) -$error = __(The username is invalid.) . ul\n + $error = __(The username is invalid.) . ul\n
Re: [aur-dev] [PATCH 2/4] test return value from db_query before assuming it is valid
hmm. looks like there were still a couple lines of formatting junk in this patch.. hilariously the ones I missed are converting spaces to tabs to be more consistent. _ the count is low though. Skimming the patch file it looks like only 3 or 4 lines. I got the big ones pruned out of the patch though.
Re: [aur-dev] [PATCH 2/4] test return value from db_query before assuming it is valid
On Wed, May 11, 2011 at 5:09 PM, Lukas Fleischer archli...@cryptocrack.de wrote: On Wed, May 11, 2011 at 04:17:12PM -0700, elij wrote: make the sql query form consistent in usage by cleaning up instances where db_query's result was not inspected before attempting to fetch row data from the handle --- web/html/addvote.php | 16 +- web/html/tu.php | 17 +-- web/lib/acctfuncs.inc | 59 web/lib/aur.inc | 8 - web/lib/pkgfuncs.inc | 43 +- web/template/actions_form.php | 52 web/template/tu_list.php | 8 +- 7 files changed, 135 insertions(+), 68 deletions(-) Looks quite ok now. Which method did you use to spot these inconsistencies? After I found and noticed one (was working on some code that triggered a php warning due to the issue, I did the following grep to find more instances. I was primarily looking for instances where db_query was being _directly_ passed to mysql_fetch_* functions. grep -R db_query /path/to/web/ | grep mysql Skimming through the source code it seems that there are some more query results that should be validated, like the SELECT one in web/html/pkgsubmit.php. Yeah, I didn't originally look for these, but I found some more with this.. grep -R -n -A1 db_query * | grep -B1 mysql That find instances where db_query is directly followed (next line) by a mysql_ function. Looking at these a few are cases of 'not testing return value of db_query before eval'. output of above command: # looks like it needs to be fixed html/pkgsubmit.php:303: $result = db_query($q, $dbh); html/pkgsubmit.php-304- $pdata = mysql_fetch_assoc($result); # this one look relatively ok. just an insert. html/pkgsubmit.php:352: db_query($q, $dbh); html/pkgsubmit.php-353- $packageID = mysql_insert_id($dbh); # looks like it needs to be fixed html/account.php:51:$result = db_query($q, $dbh); html/account.php-52-if (!mysql_num_rows($result)) { # looks like it needs to be fixed html/account.php:78:$result = db_query($q, $dbh); html/account.php-79-if (!mysql_num_rows($result)) { # looks like it needs to be fixed html/account.php:115: $result = db_query($q, $dbh); html/account.php-116- if (!mysql_num_rows($result)) { # looks like it needs to be fixed html/tu.php:28: $results = db_query($q, $dbh); html/tu.php-29- $row = mysql_fetch_assoc($results); # looks like it needs to be fixed html/tu.php:53: $result = db_query($qwhoVoted,$dbh); html/tu.php-54- if (mysql_num_rows($result) 0) { # this one is probably ok. it uses the handle to get a 'changed row count' html/passreset.php:45: $result = db_query($q, $dbh); html/passreset.php-46- if (!mysql_affected_rows($dbh)) { # looks like it needs to be fixed lib/pkgfuncs.inc:254: $result = db_query($q, $dbh); lib/pkgfuncs.inc-255- if (mysql_num_rows($result) 0) { # looks like it needs to be fixed lib/pkgfuncs.inc:637: $result = db_query($q, $dbh); lib/pkgfuncs.inc-638- if (mysql_num_rows($result)) { # looks like it needs to be fixed lib/pkgfuncs.inc:879: $result = db_query($q, $dbh); lib/pkgfuncs.inc-880- if (!mysql_num_rows($result)) { # looks like it needs to be fixed lib/stats.inc:24: $result = db_query($dbq, $dbh); lib/stats.inc-25- $row = mysql_fetch_row($result); # looks like it needs to be fixed lib/aur.inc:30: $result = db_query($q, $dbh); lib/aur.inc-31- if (mysql_num_rows($result) == 0) { # looks like it needs to be fixed lib/aur.inc:348:$result = db_query($q, $dbh); lib/aur.inc-349-if (mysql_num_rows($result) == 0) {return 1;} # looks like it needs to be fixed template/pkg_comment_form.php:31: $result = db_query($q, $dbh); template/pkg_comment_form.php-32- $row = mysql_fetch_assoc($result); Some of this could probably be cleaned up through judicious use of a few wrapper functions, with the added benefit of abstracting the sql away like we had previously talked about... Still, you eat an elephant with small bites, so I think fixing these directly for now would probably be the quickest path to resolution. This would also ease abstraction later, because it would add sensible checks at the same location where abstraction would need to test for query results anyway.
Re: [aur-dev] [PATCH] add subitter, first submitted and last modified to json output
On Tue, May 10, 2011 at 1:20 PM, kachelaqa kachel...@gmail.com wrote: this patch is a follow up to my earlier feature request (FS#24183). Does anyone really care who the original submitter was? I think maintainer makes sense, but submitter? So, while I disagree with adding submitter, I think that adding last modified is a good idea. --- web/lib/aurjson.class.php | 11 +++ 1 files changed, 7 insertions(+), 4 deletions(-) diff --git a/web/lib/aurjson.class.php b/web/lib/aurjson.class.php index 50cf6d0..2269edc 100644 --- a/web/lib/aurjson.class.php +++ b/web/lib/aurjson.class.php @@ -19,7 +19,7 @@ class AurJSON { ); private static $fields = array( 'Packages.ID', 'Name', 'Version', 'CategoryID', - 'Description', 'URL', 'License', + 'Description', 'URL', 'License', 'SubmittedTS', 'ModifiedTS', 'NumVotes', '(OutOfDateTS IS NOT NULL) AS OutOfDate' ); @@ -85,9 +85,12 @@ class AurJSON { private function process_query($type, $where_condition) { $fields = implode(',', self::$fields); - $query = SELECT Users.Username as Maintainer, {$fields} . - FROM Packages LEFT JOIN Users . - ON Packages.MaintainerUID = Users.ID . + $query = SELECT {$fields}, . + mUsers.Username AS Maintainer, . + sUsers.Username AS Submitter . + FROM Packages . + LEFT JOIN Users AS mUsers ON Packages.MaintainerUID = mUsers.ID . + LEFT JOIN Users AS sUsers ON Packages.SubmitterUID = sUsers.ID . Does this need to be a left join? I could see the need for a left join on maintainer, due to a a package not having a maintainer, but do we have any packages without a submitter? If not, then an inner join would probably be faster, since it wouldn't have to _basically_ do the inner join and THEN try to find any null columns and add those too. WHERE ${where_condition}; $result = db_query($query, $this-dbh); -- 1.7.5.1
Re: [aur-dev] [PATCH] add subitter, first submitted and last modified to json output
On Tue, May 10, 2011 at 2:04 PM, kachelaqa kachel...@gmail.com wrote: On 10/05/11 21:54, elij wrote: On Tue, May 10, 2011 at 1:20 PM, kachelaqakachel...@gmail.com wrote: this patch is a follow up to my earlier feature request (FS#24183). Does anyone really care who the original submitter was? I think maintainer makes sense, but submitter? submitter is currently shown on the package details page, as is first submitted. So, while I disagree with adding submitter, I think that adding last modified is a good idea. i think all the available information should be included. I disagree with such a broad statement as this. By that logic all comments should be included too, which I also think would be a bad idea. Perhaps you meant 'all package table data', which (while I would still disagree with in this instance) would be more reasonable. I think it makes sense to include data that is useful, while excluding data that is either unused or of very little use *in the context of the api*. In general, I am a minimalist. Also keep in mind traffic volume, and note that additional data points means more [bytes] traffic sent down the pipe to end users. The rpc is a fairly high volume interface, as Dan has previously outlined based on server logs. This point probably isn't such a large concern for the small amount of that this patch adds to the result set, but something like including comments would be very much at odds with the api design and goals. I include this point for completeness only. As an aside, I would argue that the submitter field should be removed from the aur altogether, as the current maintainer is the only really useful datapoint of the two. --- web/lib/aurjson.class.php | 11 +++ 1 files changed, 7 insertions(+), 4 deletions(-) diff --git a/web/lib/aurjson.class.php b/web/lib/aurjson.class.php index 50cf6d0..2269edc 100644 --- a/web/lib/aurjson.class.php +++ b/web/lib/aurjson.class.php @@ -19,7 +19,7 @@ class AurJSON { ); private static $fields = array( 'Packages.ID', 'Name', 'Version', 'CategoryID', - 'Description', 'URL', 'License', + 'Description', 'URL', 'License', 'SubmittedTS', 'ModifiedTS', 'NumVotes', '(OutOfDateTS IS NOT NULL) AS OutOfDate' ); @@ -85,9 +85,12 @@ class AurJSON { private function process_query($type, $where_condition) { $fields = implode(',', self::$fields); - $query = SELECT Users.Username as Maintainer, {$fields} . - FROM Packages LEFT JOIN Users . - ON Packages.MaintainerUID = Users.ID . + $query = SELECT {$fields}, . + mUsers.Username AS Maintainer, . + sUsers.Username AS Submitter . + FROM Packages . + LEFT JOIN Users AS mUsers ON Packages.MaintainerUID = mUsers.ID . + LEFT JOIN Users AS sUsers ON Packages.SubmitterUID = sUsers.ID . Does this need to be a left join? I could see the need for a left join on maintainer, due to a a package not having a maintainer, but do we have any packages without a submitter? If not, then an inner join would probably be faster, since it wouldn't have to _basically_ do the inner join and THEN try to find any null columns and add those too. okay - i will change that and re-submit the patch later. WHERE ${where_condition}; $result = db_query($query, $this-dbh); -- 1.7.5.1
[aur-dev] Couple of patches
Here are a few patches. The first patch removes the 'submitter' field from the web-ui package results. The second patch fixes several instances where db_query's result was not tested before performing mysql queries upon it. This patch might be a tad messy due to some unfortunate 'vim retab!' foolery. A result of forgetting to set noexpandtab before editing and writing out some changes. Mostly just a silly reformatting of some document strings. If the rest of the patch is wanted, I can rebase and re-edit this particular patch if desired. The third patch fixes an odd case I ran into where a user didn't exist, but a query was being performed anyway -- and relying on the sql failure to handle the lack of account. The final patch was just fixing an inconsistency I ran across, where depending on the error state, either a zero or an empty string was returned. php evaluates both to false, so it doesn't _really_ matter, but consistency is nice. :)
[aur-dev] [PATCH 2/4] test return value from db_query before assuming it is valid
make the sql query form consistent in usage by cleaning up instances where db_query's result was not inspected before attempting to fetch row data from the handle --- web/html/addvote.php | 16 +- web/html/tu.php | 17 +- web/lib/acctfuncs.inc| 59 +++ web/lib/aur.inc |8 ++- web/lib/pkgfuncs.inc | 116 + web/template/actions_form.php| 52 ++ web/template/pkg_search_form.php |2 +- web/template/tu_list.php |8 ++- 8 files changed, 172 insertions(+), 106 deletions(-) diff --git a/web/html/addvote.php b/web/html/addvote.php index 5936d56..a459610 100644 --- a/web/html/addvote.php +++ b/web/html/addvote.php @@ -21,14 +21,26 @@ if ($atype == Trusted User OR $atype == Developer) { if (!empty($_POST['user'])) { $qcheck = SELECT * FROM Users WHERE Username = ' . mysql_real_escape_string($_POST['user']) . '; - $check = mysql_num_rows(db_query($qcheck, $dbh)); + $result = db_query($qcheck, $dbh); + if ($result) { + $check = mysql_num_rows($result); + } + else { + $check = 0; + } if ($check == 0) { $error.= __(Username does not exist.); } else { $qcheck = SELECT * FROM TU_VoteInfo WHERE User = ' . mysql_real_escape_string($_POST['user']) . '; $qcheck.= AND End UNIX_TIMESTAMP(); - $check = mysql_num_rows(db_query($qcheck, $dbh)); + $result = db_query($qcheck, $dbh); + if ($result) { + $check = mysql_num_rows($result); + } + else { + $check = 0; + } if ($check != 0) { $error.= __(%s already has proposal running for them., htmlentities($_POST['user'])); diff --git a/web/html/tu.php b/web/html/tu.php index c5cc36b..6ab8ae9 100644 --- a/web/html/tu.php +++ b/web/html/tu.php @@ -36,7 +36,13 @@ if ($atype == Trusted User OR $atype == Developer) { $qvoted = SELECT * FROM TU_Votes WHERE ; $qvoted.= VoteID = . $row['ID'] . AND ; $qvoted.= UserID = . uid_from_sid($_COOKIE[AURSID]); - $hasvoted = mysql_num_rows(db_query($qvoted, $dbh)); + $result = db_query($qvoted, $dbh); + if ($result) { + $hasvoted = mysql_num_rows($result); + } + else { + $hasvoted = 0; + } # List voters of a proposal. $qwhoVoted = SELECT tv.UserID,U.Username @@ -85,10 +91,15 @@ if ($atype == Trusted User OR $atype == Developer) { $canvote = 0; $errorvote = __(You've already voted for this proposal.); # Update if they voted - $hasvoted = mysql_num_rows(db_query($qvoted, $dbh)); + $result = db_query($qvoted, $dbh); + if ($result) { + $hasvoted = mysql_num_rows($result); + } $results = db_query($q, $dbh); - $row = mysql_fetch_assoc($results); + if ($results) { + $row = mysql_fetch_assoc($results); + } } } include(tu_details.php); diff --git a/web/lib/acctfuncs.inc b/web/lib/acctfuncs.inc index 8ffa2f7..5bcff8b 100644 --- a/web/lib/acctfuncs.inc +++ b/web/lib/acctfuncs.inc @@ -197,7 +197,7 @@ function process_account_form($UTYPE,$TYPE,$A,$U=,$T=,$S=,$E=, } if (!$error !valid_username($U) !user_is_privileged($editor_user)) -$error = __(The username is invalid.) . ul\n + $error = __(The username is invalid.) . ul\n
[aur-dev] [PATCH 4/4] make return value consistent for this function
--- web/lib/aur.inc |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/web/lib/aur.inc b/web/lib/aur.inc index fb267af..f8fa715 100644 --- a/web/lib/aur.inc +++ b/web/lib/aur.inc @@ -196,7 +196,7 @@ function uid_from_sid($sid=) { $q.= AND Sessions.SessionID = ' . mysql_real_escape_string($sid) . '; $result = db_query($q, $dbh); if (!$result) { - return 0; + return ; } $row = mysql_fetch_row($result); -- 1.7.2.5
Re: [aur-dev] [PATCH 1/1] add SQL_DEBUG variable and database logging
On Wed, Apr 27, 2011 at 9:34 AM, Lukas Fleischer archli...@cryptocrack.de wrote: On Tue, Apr 26, 2011 at 11:52:11AM -0700, elij wrote: add a hook to db_query to log all sql queries when SQL_DEBUG is set Additionally, provide better logging for sql error situations (provide backtrace as well as error message). --- web/lib/aur.inc | 12 web/lib/config.inc.proto | 4 2 files changed, 16 insertions(+), 0 deletions(-) Pushed that (after fixing up stuff). I also added some note on merging config file changes to UPGRADING. Just curious, but what did you 'fixed up'?
Re: [aur-dev] [PATCH 1/1] add SQL_DEBUG variable and database logging
On Wed, Apr 27, 2011 at 1:57 PM, elij elij...@gmail.com wrote: On Wed, Apr 27, 2011 at 9:34 AM, Lukas Fleischer archli...@cryptocrack.de wrote: On Tue, Apr 26, 2011 at 11:52:11AM -0700, elij wrote: add a hook to db_query to log all sql queries when SQL_DEBUG is set Additionally, provide better logging for sql error situations (provide backtrace as well as error message). --- web/lib/aur.inc | 12 web/lib/config.inc.proto | 4 2 files changed, 16 insertions(+), 0 deletions(-) Pushed that (after fixing up stuff). I also added some note on merging config file changes to UPGRADING. Just curious, but what did you 'fixed up'? oh. nevermind. I see you just squashed the previous 'oops forgot to remove this quote mark' fixes. :)
[aur-dev] [PATCH 1/1] create variable before referencing it with .=
fixes php notice level error: Undefined variable: whovoted in ../tu.php --- web/html/tu.php |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/web/html/tu.php b/web/html/tu.php index dc1c5e3..c5cc36b 100644 --- a/web/html/tu.php +++ b/web/html/tu.php @@ -46,6 +46,7 @@ if ($atype == Trusted User OR $atype == Developer) { ORDER BY Username; $result = db_query($qwhoVoted,$dbh); if (mysql_num_rows($result) 0) { + $whovoted = ''; while ($who = mysql_fetch_assoc($result)) { $whovoted.= 'a href=account.php?Action=AccountInfoamp;ID='.$who['UserID'].''.$who['Username'].'/a '; } -- 1.7.4.1
[aur-dev] [PATCH 1/1] add SQL_DEBUG variable and database logging
add a hook to db_query to log all sql queries when SQL_DEBUG is set Additionally, provide better logging for sql error situations (provide backtrace as well as error message). --- web/lib/aur.inc | 12 web/lib/config.inc.proto |4 2 files changed, 16 insertions(+), 0 deletions(-) diff --git a/web/lib/aur.inc b/web/lib/aur.inc index 4e94340..2c6cd0d 100644 --- a/web/lib/aur.inc +++ b/web/lib/aur.inc @@ -238,10 +238,22 @@ function db_query($query=, $db_handle=) { if (!$query) { return FALSE; } + if (!$db_handle) { die(DB handle was not provided to db_query); } + + if (SQL_DEBUG == 1) { + $bt = debug_backtrace(); + error_log(DEBUG: '.$bt[0]['file'].:.$bt[0]['line']. query: $query\n); + } + $result = @mysql_query($query, $db_handle); + if (!$result) { + $bt = debug_backtrace(); + error_log(ERROR: near '.$bt[0]['file'].:.$bt[0]['line']. in query: $query\n - .mysql_error($db_handle)); + } + return $result; } diff --git a/web/lib/config.inc.proto b/web/lib/config.inc.proto index 80a7e54..43c64d2 100644 --- a/web/lib/config.inc.proto +++ b/web/lib/config.inc.proto @@ -20,6 +20,10 @@ define( PASSWD_MAX_LEN, 128 ); # Default language for displayed messages in the web interface. define(DEFAULT_LANG, en); +# Enable debug sql output. This sends each query to error_log. Useful for +# development. Should not be enabled in production. Default to 0 (off). +define(SQL_DEBUG, 0); + # Languages we have translations for $SUPPORTED_LANGS = array( ca = Català, -- 1.7.4.1
[aur-dev] [PATCH 2/2] remove stray quote mark from log output
--- web/lib/aur.inc |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/web/lib/aur.inc b/web/lib/aur.inc index 2c6cd0d..f6d6a6c 100644 --- a/web/lib/aur.inc +++ b/web/lib/aur.inc @@ -245,7 +245,7 @@ function db_query($query=, $db_handle=) { if (SQL_DEBUG == 1) { $bt = debug_backtrace(); - error_log(DEBUG: '.$bt[0]['file'].:.$bt[0]['line']. query: $query\n); + error_log(DEBUG: .$bt[0]['file'].:.$bt[0]['line']. query: $query\n); } $result = @mysql_query($query, $db_handle); -- 1.7.4.1
[aur-dev] [PATCH 3/3] remove _another_ stray quote mark from sql debug output
--- web/lib/aur.inc |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/web/lib/aur.inc b/web/lib/aur.inc index f6d6a6c..8daba0e 100644 --- a/web/lib/aur.inc +++ b/web/lib/aur.inc @@ -251,7 +251,7 @@ function db_query($query=, $db_handle=) { $result = @mysql_query($query, $db_handle); if (!$result) { $bt = debug_backtrace(); - error_log(ERROR: near '.$bt[0]['file'].:.$bt[0]['line']. in query: $query\n - .mysql_error($db_handle)); + error_log(ERROR: near .$bt[0]['file'].:.$bt[0]['line']. in query: $query\n - .mysql_error($db_handle)); } return $result; -- 1.7.4.1
[aur-dev] some notes from converting the aur from mysql to postgresql
While converting the aur codebase from mysql to postgresql (just for fun/to see if I could), I ran into a few mysql specific gotchas, and a few oddities. Here are some of my notes from the experience. * I ran into a few sql integer comparisons that are using string comparisons. postgres didn't like this, but mysql was fine with it ex: `$q .= WHERE s.UsersId = ' . $userID . ' ;` * using the limit offset format of `LIMIT x,y` postgresql doesn't support this format, so I had to track each occurrence down and change it to `Limit x OFFSET y` * A few instances of `LIMIT 0,10`. A `LIMIT 10` would have been sufficient. Not sure why offset was specified in these few instances. * A pair of column names were reserved words. user' and 'end' in the TU_VoteInfo table. I changed the column names to username and ending, to avoid issues and/or having to quote the name all the time. * postgresql table and column names are lowercase (when not quoted). This required me to either quote all instances of table and column names (ugh) or change the fetch_assoc php references to lowercase. I chose the latter, even though it was tedious to track down all instances and change them. * postgres has no mysql_insert_id counterpart. Instead I appended to the query RETURNING ID and then used pg_fetch_result to get the ID that was created. * postgres LIKE and ILIKE queries did full table scans, and was quite slow. I think mysql was caching these queries when I was doing my performance tests. The end result was postgres performing poorly in my load test for LIKE/ILIKE operations. So I created a postgres fulltext search column for the packages table, indexed it, defined triggers to keep it udpated, and converted to using postgres fulltext searching `@@ to_tsquery('term')`. The result was quite speedy and gave nice results. The syntax was a bit different for 'prefix searching' though, and the results were not the same as the LIKE/ILIKE queries, because fulltext uses stemming instead of partial string comparison. * There is quite a bit of sql code sprinkled all over the place. It might make sense to try and consolidate some of the sql to fewer files. * It might make sense to generalize the 'mysql_real_escape_string' instances to a wrapper 'db_escape' or something similar. This would could make things a bit cleaner, ease possible future porting to other databases (fewer things to track down and change individually). * postgres doesn't support `UNIX_TIMESTAMP()`. Instead of changing all instances of it, I defined a few convenience sql functions. -- -- helper functions to ease conversion from mysql -- from: http://janusz.slota.name/blog/2009/06/mysql-from_unixtime-and-unix_timestamp-functions-in-postgresql/ -- -- no params CREATE OR REPLACE FUNCTION unix_timestamp() RETURNS BIGINT AS ' SELECT EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::bigint AS result; ' LANGUAGE 'SQL'; -- timestamp without time zone (i.e. 1973-11-29 21:33:09) CREATE OR REPLACE FUNCTION unix_timestamp(TIMESTAMP) RETURNS BIGINT AS ' SELECT EXTRACT(EPOCH FROM $1)::bigint AS result; ' LANGUAGE 'SQL'; -- timestamp with time zone (i.e. 1973-11-29 21:33:09+01) CREATE OR REPLACE FUNCTION unix_timestamp(TIMESTAMP WITH TIME zone) RETURNS BIGINT AS ' SELECT EXTRACT(EPOCH FROM $1)::bigint AS result; ' LANGUAGE 'SQL'; I think that is it.
Re: [aur-dev] some notes from converting the aur from mysql to postgresql
On Mon, Apr 25, 2011 at 7:49 PM, Dan McGee dpmc...@gmail.com wrote: On Mon, Apr 25, 2011 at 9:35 PM, elij elij...@gmail.com wrote: While converting the aur codebase from mysql to postgresql (just for fun/to see if I could), I ran into a few mysql specific gotchas, and a few oddities. Here are some of my notes from the experience. Mind sending the diff along for funzies? Even if we can't apply it as a patch, it would be good to see and maybe chop up into this will be compatible with all DBs so we should fix it anyway and if we switch we will need to look into this. Sure. I will probably just do a git-format patch and dump the patches into a tarball and upload it somewhere, since it is quite large, and not exactly 'split into single change patches'. ;) * I ran into a few sql integer comparisons that are using string comparisons. postgres didn't like this, but mysql was fine with it ex: `$q .= WHERE s.UsersId = ' . $userID . ' ;` Should definitely be fixed anyway...awesome. Yeah. Some of these fixes in the above patchset are wrapped up in other things, but I can try to split out the these can be fixed regardless and there were fixes to get postgres working. * using the limit offset format of `LIMIT x,y` postgresql doesn't support this format, so I had to track each occurrence down and change it to `Limit x OFFSET y` This is SQL standard, so you could use this form anyway, correct? Of course the MySQL docs claim this: For compatibility with PostgreSQL, MySQL also supports the LIMIT row_count OFFSET offset syntax. Yeah. LIMIT w/OFFSET is sql standard. Not sure why mysql had to create their own limit/offset standard, but well.. yeah. * A few instances of `LIMIT 0,10`. A `LIMIT 10` would have been sufficient. Not sure why offset was specified in these few instances. Sure it wasn't auto-generated, in which case it is easier for the DB query analyzer to just throw it away anyway? It looks like there were just two instances. web/html/rss.php: $q = SELECT * FROM Packages ; $q.= WHERE DummyPkg != 1 ; $q.= ORDER BY SubmittedTS DESC ; $q.= LIMIT 0 , 20; web/lib/stats.inc: $q = 'SELECT * FROM Packages WHERE DummyPkg != 1 ORDER BY GREATEST(SubmittedTS,ModifiedTS) DESC LIMIT 0 , 10'; * A pair of column names were reserved words. user' and 'end' in the TU_VoteInfo table. I changed the column names to username and ending, to avoid issues and/or having to quote the name all the time. * postgresql table and column names are lowercase (when not quoted). This required me to either quote all instances of table and column names (ugh) or change the fetch_assoc php references to lowercase. I chose the latter, even though it was tedious to track down all instances and change them. * postgres has no mysql_insert_id counterpart. Instead I appended to the query RETURNING ID and then used pg_fetch_result to get the ID that was created. * postgres LIKE and ILIKE queries did full table scans, and was quite slow. I think mysql was caching these queries when I was doing my performance tests. The end result was postgres performing poorly in my load test for LIKE/ILIKE operations. So I created a postgres fulltext search column for the packages table, indexed it, defined triggers to keep it udpated, and converted to using postgres fulltext searching `@@ to_tsquery('term')`. The result was quite speedy and gave nice results. The syntax was a bit different for 'prefix searching' though, and the results were not the same as the LIKE/ILIKE queries, because fulltext uses stemming instead of partial string comparison. And case sensitivity would come into play, no? I built the fulltext index as follows: alter table packages add column tsv tsvector; update packages set tsv = to_tsvector('english', coalesce(lower(name), '') || ' ' || coalesce(lower(description), '')); then added a trigger to update it for new data: DROP FUNCTION IF EXISTS package_fulltext_trigger() CASCADE; CREATE FUNCTION package_fulltext_trigger() RETURNS trigger as $$ begin new.tsv := setweight(to_tsvector('english', coalesce(lower(new.name), '')), 'A') || setweight(to_tsvector('english', coalesce(lower(new.description), '')), 'B'); return new; end $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS packages_tsv_update; CREATE TRIGGER packages_tsv_update BEFORE INSERT OR UPDATE on packages FOR EACH ROW EXECUTE PROCEDURE package_fulltext_trigger(); * There is quite a bit of sql code sprinkled all over the place. It might make sense to try and consolidate some of the sql to fewer files. * It might make sense to generalize the 'mysql_real_escape_string' instances to a wrapper 'db_escape' or something similar. This would could make things a bit cleaner, ease possible future porting to other databases (fewer things to track down and change individually). * postgres doesn't support `UNIX_TIMESTAMP()`. Instead of changing all
Re: [aur-dev] some notes from converting the aur from mysql to postgresql
On Mon, Apr 25, 2011 at 8:38 PM, elij elij...@gmail.com wrote: On Mon, Apr 25, 2011 at 7:49 PM, Dan McGee dpmc...@gmail.com wrote: And case sensitivity would come into play, no? I built the fulltext index as follows: alter table packages add column tsv tsvector; update packages set tsv = to_tsvector('english', coalesce(lower(name), '') || ' ' || coalesce(lower(description), '')); then added a trigger to update it for new data: DROP FUNCTION IF EXISTS package_fulltext_trigger() CASCADE; CREATE FUNCTION package_fulltext_trigger() RETURNS trigger as $$ begin new.tsv := setweight(to_tsvector('english', coalesce(lower(new.name), '')), 'A') || setweight(to_tsvector('english', coalesce(lower(new.description), '')), 'B'); return new; end $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS packages_tsv_update; CREATE TRIGGER packages_tsv_update BEFORE INSERT OR UPDATE on packages FOR EACH ROW EXECUTE PROCEDURE package_fulltext_trigger(); oops. Forgot to complete that thought.. thus, it is case insensitive because everything is lowercased before turning it into a fulltext tsvector. The search input would probably need to be lowered as well, for the above implementation.
Re: [aur-dev] some notes from converting the aur from mysql to postgresql
On Mon, Apr 25, 2011 at 8:50 PM, Dan McGee dpmc...@gmail.com wrote: On Mon, Apr 25, 2011 at 10:38 PM, elij elij...@gmail.com wrote: On Mon, Apr 25, 2011 at 7:49 PM, Dan McGee dpmc...@gmail.com wrote: On Mon, Apr 25, 2011 at 9:35 PM, elij elij...@gmail.com wrote: * using the limit offset format of `LIMIT x,y` postgresql doesn't support this format, so I had to track each occurrence down and change it to `Limit x OFFSET y` This is SQL standard, so you could use this form anyway, correct? Of course the MySQL docs claim this: For compatibility with PostgreSQL, MySQL also supports the LIMIT row_count OFFSET offset syntax. Yeah. LIMIT w/OFFSET is sql standard. Not sure why mysql had to create their own limit/offset standard, but well.. yeah. * A few instances of `LIMIT 0,10`. A `LIMIT 10` would have been sufficient. Not sure why offset was specified in these few instances. Sure it wasn't auto-generated, in which case it is easier for the DB query analyzer to just throw it away anyway? It looks like there were just two instances. web/html/rss.php: $q = SELECT * FROM Packages ; $q.= WHERE DummyPkg != 1 ; $q.= ORDER BY SubmittedTS DESC ; $q.= LIMIT 0 , 20; web/lib/stats.inc: $q = 'SELECT * FROM Packages WHERE DummyPkg != 1 ORDER BY GREATEST(SubmittedTS,ModifiedTS) DESC LIMIT 0 , 10'; If you still have DummyPkg references, you might need to update your codebase- this was killed a while ago by me. With that said, the first one still exists; the second one was fixed in the aforementioned update. Ah. Yeah, I probably do need to do a pull and merge (been a while). Thanks for the heads up.
[aur-dev] [PATCH 1/1] convert mysql specific offset/limit syntax to more standardized format
--- web/html/rss.php |2 +- web/html/tu.php |2 +- web/lib/acctfuncs.inc |2 +- web/lib/pkgfuncs.inc |2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/web/html/rss.php b/web/html/rss.php index cb0bf40..0547815 100644 --- a/web/html/rss.php +++ b/web/html/rss.php @@ -32,7 +32,7 @@ $rss-image = $image; $dbh = db_connect(); $q = SELECT * FROM Packages ; $q.= ORDER BY SubmittedTS DESC ; -$q.= LIMIT 0 , 20; +$q.= LIMIT 20; $result = db_query($q, $dbh); while ($row = mysql_fetch_assoc($result)) { diff --git a/web/html/tu.php b/web/html/tu.php index 941e6ed..dc1c5e3 100644 --- a/web/html/tu.php +++ b/web/html/tu.php @@ -119,7 +119,7 @@ if ($atype == Trusted User OR $atype == Developer) { } $order = ($by == 'asc') ? 'ASC' : 'DESC'; - $lim = ($limit 0) ? LIMIT $off, $limit : ; + $lim = ($limit 0) ? LIMIT $limit OFFSET $off : ; $by_next = ($by == 'desc') ? 'asc' : 'desc'; $q = SELECT * FROM TU_VoteInfo WHERE End . time() . ORDER BY Submitted . $order; diff --git a/web/lib/acctfuncs.inc b/web/lib/acctfuncs.inc index fe1cfb1..f07c1fc 100644 --- a/web/lib/acctfuncs.inc +++ b/web/lib/acctfuncs.inc @@ -405,7 +405,7 @@ function search_results_page($UTYPE,$O=0,$SB=,$U=,$T=, break; } $search_vars[] = SB; - $q.= LIMIT . $OFFSET . , . $HITS_PER_PAGE; + $q.= LIMIT {$HITS_PER_PAGE} OFFSET {$OFFSET}; $dbh = db_connect(); diff --git a/web/lib/pkgfuncs.inc b/web/lib/pkgfuncs.inc index 8f90d0e..25a09c4 100644 --- a/web/lib/pkgfuncs.inc +++ b/web/lib/pkgfuncs.inc @@ -501,7 +501,7 @@ function pkg_search_page($SID=) { break; } - $q_limit = LIMIT .$_GET[O]., .$_GET[PP]; + $q_limit = LIMIT {$_GET[PP]} OFFSET {$_GET[O]}; $q = $q_select . $q_from . $q_from_extra . $q_where . $q_sort . $q_limit; $q_total = SELECT COUNT(*) . $q_from . $q_where; -- 1.7.4.1
Re: [aur-dev] [PATCH 1/1] convert mysql specific offset/limit syntax to more standardized format
On Mon, Apr 25, 2011 at 9:31 PM, Dan McGee dpmc...@gmail.com wrote: On Mon, Apr 25, 2011 at 11:17 PM, elij elij...@gmail.com wrote: --- web/html/rss.php | 2 +- web/html/tu.php | 2 +- web/lib/acctfuncs.inc | 2 +- web/lib/pkgfuncs.inc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) Haha, patch war! :P We have nearly identical patches here; the only thing different is string concatenation/variable replacement. It appears we went opposite directions. I did concatenation rather than replacement as it seemed to be the standard in the codebase, and looking at + $q_limit = LIMIT {$_GET[PP]} OFFSET {$_GET[O]}; made me puke a little in my mouth first before I went the way I did. Ha! I feel like that looking at php code in general! I saw a mess of . ' . and did a bit of a lolwut myself. I don't think either mechanism looks good honestly. Too bad php doesn't have decent string formatting. :/ I am tempted to use sprintf! Note that I failboated a bit and used double-quote inside the substitution elements. I just used what existed, but single quote would have been better. That said, using string catenation is probably better for code uniformity sake (since everything else does it _most of the time_. I also saw things referencing memory leaks with variable substitution, but that is likely old. It does appear concatenation is slightly faster [1], however, not that we are anywhere near the point where this matters. :) lol. -Dan [1] http://www.webmasterworld.com/forum88/3253.htm (benchmarks from post-2004 welcome!) diff --git a/web/html/rss.php b/web/html/rss.php index cb0bf40..0547815 100644 --- a/web/html/rss.php +++ b/web/html/rss.php @@ -32,7 +32,7 @@ $rss-image = $image; $dbh = db_connect(); $q = SELECT * FROM Packages ; $q.= ORDER BY SubmittedTS DESC ; -$q.= LIMIT 0 , 20; +$q.= LIMIT 20; $result = db_query($q, $dbh); while ($row = mysql_fetch_assoc($result)) { diff --git a/web/html/tu.php b/web/html/tu.php index 941e6ed..dc1c5e3 100644 --- a/web/html/tu.php +++ b/web/html/tu.php @@ -119,7 +119,7 @@ if ($atype == Trusted User OR $atype == Developer) { } $order = ($by == 'asc') ? 'ASC' : 'DESC'; - $lim = ($limit 0) ? LIMIT $off, $limit : ; + $lim = ($limit 0) ? LIMIT $limit OFFSET $off : ; $by_next = ($by == 'desc') ? 'asc' : 'desc'; $q = SELECT * FROM TU_VoteInfo WHERE End . time() . ORDER BY Submitted . $order; diff --git a/web/lib/acctfuncs.inc b/web/lib/acctfuncs.inc index fe1cfb1..f07c1fc 100644 --- a/web/lib/acctfuncs.inc +++ b/web/lib/acctfuncs.inc @@ -405,7 +405,7 @@ function search_results_page($UTYPE,$O=0,$SB=,$U=,$T=, break; } $search_vars[] = SB; - $q.= LIMIT . $OFFSET . , . $HITS_PER_PAGE; + $q.= LIMIT {$HITS_PER_PAGE} OFFSET {$OFFSET}; $dbh = db_connect(); diff --git a/web/lib/pkgfuncs.inc b/web/lib/pkgfuncs.inc index 8f90d0e..25a09c4 100644 --- a/web/lib/pkgfuncs.inc +++ b/web/lib/pkgfuncs.inc @@ -501,7 +501,7 @@ function pkg_search_page($SID=) { break; } - $q_limit = LIMIT .$_GET[O]., .$_GET[PP]; + $q_limit = LIMIT {$_GET[PP]} OFFSET {$_GET[O]}; $q = $q_select . $q_from . $q_from_extra . $q_where . $q_sort . $q_limit; $q_total = SELECT COUNT(*) . $q_from . $q_where; -- 1.7.4.1
Re: [aur-dev] [PATCH 2/3] SQL: treat all UID/ID values as numbers, not strings
On Mon, Apr 25, 2011 at 9:23 PM, Dan McGee d...@archlinux.org wrote: Ensure we are not quoting these values in any of our SQL queries. wewt! Thanks-to: elij elij...@gmail.com Signed-off-by: Dan McGee d...@archlinux.org --- Smoke tested: * Submitted a package update and it worked * Updated a user's password from non-salted to salted variety * Numerous login/logout cycles web/html/passreset.php | 4 ++-- web/html/pkgsubmit.php | 2 +- web/lib/acctfuncs.inc | 18 +- web/lib/aur.inc | 6 +++--- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/web/html/passreset.php b/web/html/passreset.php index 2c7801d..0ce6f7d 100644 --- a/web/html/passreset.php +++ b/web/html/passreset.php @@ -58,8 +58,8 @@ if (isset($_GET['resetkey'], $_POST['email'], $_POST['password'], $_POST['confir $resetkey = new_sid(); $dbh = db_connect(); $q = UPDATE Users - SET ResetKey = '$resetkey' - WHERE ID = '$uid'; + SET ResetKey = ' . $resetkey . ' + WHERE ID = . $uid; db_query($q, $dbh); # Send email with confirmation link $body = __('A password reset request was submitted for the account '. diff --git a/web/html/pkgsubmit.php b/web/html/pkgsubmit.php index 5797626..3ef5823 100644 --- a/web/html/pkgsubmit.php +++ b/web/html/pkgsubmit.php @@ -320,7 +320,7 @@ if ($_COOKIE[AURSID]): } # Update package data - $q = sprintf(UPDATE Packages SET ModifiedTS = UNIX_TIMESTAMP(), Name = '%s', Version = '%s-%s', License = '%s', Description = '%s', URL = '%s', OutOfDateTS = NULL, MaintainerUID = '%d' WHERE ID = %d, + $q = sprintf(UPDATE Packages SET ModifiedTS = UNIX_TIMESTAMP(), Name = '%s', Version = '%s-%s', License = '%s', Description = '%s', URL = '%s', OutOfDateTS = NULL, MaintainerUID = %d WHERE ID = %d, mysql_real_escape_string($new_pkgbuild['pkgname']), mysql_real_escape_string($new_pkgbuild['pkgver']), mysql_real_escape_string($new_pkgbuild['pkgrel']), diff --git a/web/lib/acctfuncs.inc b/web/lib/acctfuncs.inc index 8e2ecb3..8ffa2f7 100644 --- a/web/lib/acctfuncs.inc +++ b/web/lib/acctfuncs.inc @@ -619,18 +619,18 @@ function try_login() { # last ($MAX_SESSIONS_PER_USER - 1). $q = DELETE s.* FROM Sessions s ; $q.= LEFT JOIN (SELECT SessionID FROM Sessions ; - $q.= WHERE UsersId = ' . $userID . ' ; + $q.= WHERE UsersId = . $userID . ; $q.= ORDER BY LastUpdateTS DESC ; $q.= LIMIT . ($MAX_SESSIONS_PER_USER - 1) . ) q ; $q.= ON s.SessionID = q.SessionID ; - $q.= WHERE s.UsersId = ' . $userID . ' ; + $q.= WHERE s.UsersId = . $userID . ; $q.= AND q.SessionID IS NULL;; db_query($q, $dbh); } $new_sid = new_sid(); $q = INSERT INTO Sessions (UsersID, SessionID, LastUpdateTS) - . VALUES ( $userID, ' . $new_sid . ', UNIX_TIMESTAMP()); + . VALUES ( . $userID . , ' . $new_sid . ', UNIX_TIMESTAMP()); $result = db_query($q, $dbh); # Query will fail if $new_sid is not unique @@ -749,7 +749,7 @@ function valid_passwd( $userID, $passwd ) if ($salt) { # use salt $passwd_q = SELECT ID FROM Users . - WHERE ID = '$userID' AND Passwd = ' . + WHERE ID = . $userID . AND Passwd = ' . salted_hash($passwd, $salt) . '; $passwd_result = mysql_fetch_row(db_query($passwd_q, $dbh)); if ($passwd_result[0]) { @@ -758,14 +758,14 @@ function valid_passwd( $userID, $passwd ) } else { # check without salt $nosalt_q = SELECT ID FROM Users. - WHERE ID = '$userID' . + WHERE ID = . $userID . AND Passwd = ' . md5($passwd) . '; $nosalt_result
[aur-dev] [PATCH 1/1] use convenience wrapper for mysql_real_escape_string to aid database portability
when converting to postgres, each mysql_real_escape_string instance had to be changed, which was tedious. Centralizing the escape mechanism code would allow for much easier porting, in the same way that db_query provides a lightweight query abstraction. --- web/html/account.php |2 +- web/html/addvote.php | 10 +- web/html/logout.php |2 +- web/html/passreset.php|4 ++-- web/html/pkgsubmit.php| 36 ++-- web/html/voters.php |2 +- web/lib/acctfuncs.inc | 26 +- web/lib/aur.inc | 30 ++ web/lib/aurjson.class.php |8 web/lib/pkgfuncs.inc | 12 ++-- web/lib/stats.inc |2 +- web/template/pkg_comment_form.php |2 +- 12 files changed, 71 insertions(+), 65 deletions(-) diff --git a/web/html/account.php b/web/html/account.php index afb0d7c..029ae79 100644 --- a/web/html/account.php +++ b/web/html/account.php @@ -111,7 +111,7 @@ if (isset($_COOKIE[AURSID])) { $q.= WHERE AccountTypes.ID = Users.AccountTypeID ; $q.= AND Users.ID = Sessions.UsersID ; $q.= AND Sessions.SessionID = '; - $q.= mysql_real_escape_string($_COOKIE[AURSID]).'; + $q.= db_escape($_COOKIE[AURSID]).'; $result = db_query($q, $dbh); if (!mysql_num_rows($result)) { print __(Could not retrieve information for the specified user.); diff --git a/web/html/addvote.php b/web/html/addvote.php index 5936d56..e039d06 100644 --- a/web/html/addvote.php +++ b/web/html/addvote.php @@ -20,13 +20,13 @@ if ($atype == Trusted User OR $atype == Developer) { $error = ; if (!empty($_POST['user'])) { - $qcheck = SELECT * FROM Users WHERE Username = ' . mysql_real_escape_string($_POST['user']) . '; + $qcheck = SELECT * FROM Users WHERE Username = ' . db_escape($_POST['user']) . '; $check = mysql_num_rows(db_query($qcheck, $dbh)); if ($check == 0) { $error.= __(Username does not exist.); } else { - $qcheck = SELECT * FROM TU_VoteInfo WHERE User = ' . mysql_real_escape_string($_POST['user']) . '; + $qcheck = SELECT * FROM TU_VoteInfo WHERE User = ' . db_escape($_POST['user']) . '; $qcheck.= AND End UNIX_TIMESTAMP(); $check = mysql_num_rows(db_query($qcheck, $dbh)); @@ -55,9 +55,9 @@ if ($atype == Trusted User OR $atype == Developer) { if (!empty($_POST['addVote']) empty($error)) { $q = INSERT INTO TU_VoteInfo (Agenda, User, Submitted, End, SubmitterID) VALUES ; - $q.= (' . mysql_real_escape_string($_POST['agenda']) . ', ; - $q.= ' . mysql_real_escape_string($_POST['user']) . ', ; - $q.= UNIX_TIMESTAMP(), UNIX_TIMESTAMP() + . mysql_real_escape_string($len); + $q.= (' . db_escape($_POST['agenda']) . ', ; + $q.= ' . db_escape($_POST['user']) . ', ; + $q.= UNIX_TIMESTAMP(), UNIX_TIMESTAMP() + . db_escape($len); $q.= , . uid_from_sid($_COOKIE[AURSID]) . ); db_query($q, $dbh); diff --git a/web/html/logout.php b/web/html/logout.php index 95cf460..ffde619 100644 --- a/web/html/logout.php +++ b/web/html/logout.php @@ -12,7 +12,7 @@ include_once(acctfuncs.inc); # access AUR common functions if (isset($_COOKIE[AURSID])) { $dbh = db_connect(); $q = DELETE FROM Sessions WHERE SessionID = '; - $q.= mysql_real_escape_string($_COOKIE[AURSID]) . '; + $q.= db_escape($_COOKIE[AURSID]) . '; db_query($q, $dbh); # setting expiration to 1 means '1 second after midnight January 1, 1970' setcookie(AURSID, , 1, /); diff --git a/web/html/passreset.php b/web/html/passreset.php index 2c7801d..daba63e 100644 --- a/web/html/passreset.php +++ b/web/html/passreset.php @@ -40,8 +40,8 @@ if (isset($_GET['resetkey'], $_POST['email'], $_POST['password'], $_POST['confir Salt = '$salt', ResetKey = '' WHERE ResetKey != '' - AND ResetKey = '.mysql_real_escape_string($resetkey).' - AND Email = '.mysql_real_escape_string($email).'; + AND ResetKey = '.db_escape($resetkey).' + AND Email = '.db_escape($email).'; $result = db_query($q, $dbh); if (!mysql_affected_rows($dbh)) { $error = __('Invalid e-mail and reset key
Re: [aur-dev] [PATCH 4/4] rpc: allow multiple args on info query
On Mon, Apr 11, 2011 at 10:15 PM, Dan McGee d...@archlinux.org wrote: [1] Rough data from April 11, 2011, with a total hit count of 1,109,163: 12 /login.php 13 /rpc.php?type=sarch 15 /rpc.php?type=msearch 16 /pingserver.php 16 /rpc.php 22 /logout.php 163 /passreset.php 335 /account.php 530 /pkgsubmit.php 916 /rss2.php 3838 /index.php 6752 /rss.php 9699 / 42478 /rpc.php?type=search 184737 /packages.php 681725 /rpc.php?type=info That means a whopping 61.5% of our requests were for info over the RPC interface; package pages are a distant second at only 16.7%. I had a question about this data. What is the breakdown of those 'info' type queries that are querying by ID vs by Name. There was a time (pre-2009) when the search endpoint result set wasn't quite as complete as the info result set. I am wondering if the preponderance of info style queries could be very legacy clients that are first searching, then performing 'by id' or 'by name' lookups to populate the result set for the end user. The fact that the search result set is now just as complete as the info result set, could possibly provide an avenue to help alleviate load if said clients were identified/fixed/updated. Additionally, if the 'ID' type queries are a low percentage, it may be a good idea to just drop that and simply do exact package name equality comparisons. This would also be more consistent as ID is more for internal database representation, names are unique, and search does not allow searching based on partial ID matches (which would be silly). This would also rule out the need for 'server side ordering' as you get back a list of packages, from a list of submitted names, and you can order/sort/identify them client side very easily (no ambiguity of trying to deal with whether it was an info result based on a name, or based on an id search term).
Re: [aur-dev] [PATCH 4/4] rpc: allow multiple args on info query
On Mon, Apr 11, 2011 at 10:15 PM, Dan McGee d...@archlinux.org wrote: The majority of real world info requests [1] come in hefty batches. We would be better served to handle these in one request rather than multiple by allowing AUR clients to send multiple arguments. This enables things like this to work: http://aur.test/rpc.php?type=infoarg[]=cups-xeroxarg[]=cups-mc2430dlarg[]=10673 This kind of breaks the query format convention (thanks php!). It might be cleaner to use a separator (like a space) to break up args (and simply split on space). http://aur.test/rpc.php?type=infoarg=cups-xerox+cups-mc1430dl+10673 (note using plus signs here as an example since spaces or %20s are harder to 'see') Note to RPC users: unfortunately due to the asinine design of PHP, you unfortunately have to use the 'arg[]' syntax if you want more than one query argument, or you will only get the package satisfying the last arg you pass. [1] Rough data from April 11, 2011, with a total hit count of 1,109,163: 12 /login.php 13 /rpc.php?type=sarch 15 /rpc.php?type=msearch 16 /pingserver.php 16 /rpc.php 22 /logout.php 163 /passreset.php 335 /account.php 530 /pkgsubmit.php 916 /rss2.php 3838 /index.php 6752 /rss.php 9699 / 42478 /rpc.php?type=search 184737 /packages.php 681725 /rpc.php?type=info That means a whopping 61.5% of our requests were for info over the RPC interface; package pages are a distant second at only 16.7%. Signed-off-by: Dan McGee d...@archlinux.org --- web/lib/aurjson.class.php | 59 1 files changed, 48 insertions(+), 11 deletions(-) diff --git a/web/lib/aurjson.class.php b/web/lib/aurjson.class.php index 9b0e1a0..57096d8 100644 --- a/web/lib/aurjson.class.php +++ b/web/lib/aurjson.class.php @@ -101,6 +101,36 @@ class AurJSON { } /** + * Parse the args to the info function. We may have a string or an array, + * so do the appropriate thing. Within the elements, both * package IDs + * and package names are valid; sort them into the relevant arrays and + * escape/quote the names. + * @param $args the arg string or array to parse. + * @return mixed An array containing 'ids' and 'names'. + **/ + private function parse_info_args($args) { + if (!is_array($args)) { + $args = array($args); + } + + $id_args = array(); + $name_args = array(); + foreach ($args as $arg) { + if (!$arg) { + continue; + } + if (is_numeric($arg)) { + $id_args[] = intval($arg); + } else { + $escaped = mysql_real_escape_string($arg, $this-dbh); + $name_args[] = ' . $escaped . '; + } + } + + return array('ids' = $id_args, 'names' = $name_args); + } + + /** * Performs a fulltext mysql search of the package database. * @param $keyword_string A string of keywords to search with. * @return mixed Returns an array of package matches. @@ -129,21 +159,28 @@ class AurJSON { **/ private function info($pqdata) { $fields = implode(',', self::$fields); + $args = $this-parse_info_args($pqdata); + $ids = $args['ids']; + $names = $args['names']; - $base_query = SELECT {$fields} . - FROM Packages WHERE ; + if (!$ids !$names) { + return $this-json_error('Invalid query arguments'); + } - if ( is_numeric($pqdata) ) { - // just using sprintf to coerce the pqd to an int - // should handle sql injection issues, since sprintf will - // bork if not an int, or convert the string to a number 0 - $query_stub = ID={$pqdata}; + $query = SELECT {$fields} . + FROM Packages WHERE ; + if ($ids) { + $ids_value = implode(',', $args['ids']); + $query .= ID IN ({$ids_value}); I thought 'where in' queries in mysql were known to be terribly slow compared to using 'where ='. } - else { - $query_stub = sprintf(Name=\%s\, - mysql_real_escape_string($pqdata, $this-dbh)); + if ($ids $names) { + $query .= OR ; + } + if ($names) { + // individual names were quoted in parse_info_args() + $names_value = implode(',', $args['names']); + $query .= Name IN ({$names_value}); } - $query = $base_query . $query_stub; return $this-process_query('info', $query); } -- 1.7.4.4
Re: [aur-dev] [PATCH 1/4] make gendummydata script more friendly
On Tue, Apr 5, 2011 at 11:20 PM, Rémy Oudompheng remyoudomph...@gmail.com wrote: On Tue 05 April 2011 at 17:54 -0700, elij wrote: - no need to use mysql - just considering categories as an integer range, specified to the size of that in the aur-schema. So does this produce valid SQL commands ? Why don't you escape the strings anymore ? - use logging module instead of writing directly to stderr this makes the code cleaner as there is only one test for the value of DBUG. Why is this in the same patch? And I don't really see the point of using the logging module here: it seems to spam the user with dozens of DEBUG: working... where the previous little dots actually looked nice. I removed that in a later patch. Because of the space format issue previously mentioned, I didn't squash history and turn it into a giant single patch. --- support/schema/gendummydata.py | 100 +--- 1 files changed, 32 insertions(+), 68 deletions(-) diff --git a/support/schema/gendummydata.py b/support/schema/gendummydata.py index 7b1d0cf..47d9bd5 100755 --- a/support/schema/gendummydata.py +++ b/support/schema/gendummydata.py @@ -15,7 +15,8 @@ import os import sys import cStringIO import commands - +import logging +import re Where is the re module used ? I forgot to remove this. I had used it at one point for extracting the category names from the aur-schema.sql file, but then realized that it was a pointless endeavor. The names are not used to generate the package data, just the IDs. Since the category ID for a dummydata package is chosen via randomization, just choosing a random number from 0 to count_of_categories is enough. In the case of the current AUR, that is 17. I made it a variable right along side many of the other variables. Looks like I need to cleanup my patch set a bit. DBUG = 1 SEED_FILE = /usr/share/dict/words @@ -33,6 +34,7 @@ PKG_FILES = (8, 30) # min/max number of files in a package PKG_DEPS = (1, 5) # min/max depends a package has PKG_SRC = (1, 3) # min/max sources a package has PKG_CMNTS = (1, 5) # min/max number of comments a package has +CATEGORIES_COUNT = 17 # the number of categories from aur-schema I am wondering whether something like counting the matching lines in aur-schema.sql would not be a better idea. I think the schema for the number of categories changes so seldom, that it would be pointless. If the count of categories is increased beyond 17, there simply would be no test packages with that category (not a critical failure). If the names of the categories change, it would not matter at all (only IDs used). The only case that counts is if categories are removed. In that case, update the variable.
Re: [aur-dev] [PATCH 3/4] reformat
On Tue, Apr 5, 2011 at 11:25 PM, Rémy Oudompheng remyoudomph...@gmail.com wrote: On Tue 05 April 2011 at 17:54 -0700, elij wrote: - make the sql nicer and more readable - convert to spaces. who uses tabs in python!? As far as I know, we use tabs in all of our Python projects. Sorry to hear it. :)
Re: [aur-dev] [PATCH 1/3] make gendummydata script more friendly
On Wed, Apr 6, 2011 at 12:04 PM, Lukas Fleischer archli...@cryptocrack.de wrote: I agree with both changes, but please split that one into two separate patches. ugh. yeah I can probably do that. -DBUG = 1 +log_level = logging.DEBUG # logging level. set to logging.INFO to reduce output I'm not a Python coder, but is there any reason to use lowercase here whereas we use uppercase for all other constants? No reason really. I am just not used to uppercasing variables. When I refactor to split the above changes I will try to remember to make that variable format similar to the others. raise SystemExit Shouldn't we rather use sys.exit(1); here instead of raising a SystemExit exception? That way we'd have a proper exit status, also. Might be something to include in the debugging/error handling patch. Possibly. sys.exit actually raises SystemExit, if I remember correctly. Setting a shell exit value is a good idea though. I will add that in. num_comments = random.randrange(PKG_CMNTS[0], PKG_CMNTS[1]) for i in range(0, num_comments): - fortune = esc(commands.getoutput(FORTUNE_CMD).replace(',)) + fortune = commands.getoutput(FORTUNE_CMD).replace(',) Why did you drop escape_string() here? It relies upon mysql, and since the other instance of mysql usage was removed by one of my patches, I removed this as well (to remove the dep entirely). For dummy data there really isn't a danger of sql injection, and removing ' characters from the fortune_cmd result string should be enough to keep from causing the written sql to be badly formatted.
[aur-dev] [PATCH 3/4] wrap long SQL commands to improve formatting and readability
--- support/schema/gendummydata.py | 34 +++--- 1 files changed, 23 insertions(+), 11 deletions(-) diff --git a/support/schema/gendummydata.py b/support/schema/gendummydata.py index 290002a..cb27f9c 100755 --- a/support/schema/gendummydata.py +++ b/support/schema/gendummydata.py @@ -167,7 +167,9 @@ for u in user_keys: # pass - s = INSERT INTO Users (ID, AccountTypeID, Username, Email, Passwd) VALUES (%d, %d, '%s', '%s...@example.com', MD5('%s'));\n % (seen_users[u], account_type, u, u, u) + s = (INSERT INTO Users (ID, AccountTypeID, Username, Email, Passwd) + VALUES (%d, %d, '%s', '%s...@example.com', MD5('%s'));\n) + s = s % (seen_users[u], account_type, u, u, u) out.write(s) log.debug(Number of developers: %d % len(developers)) @@ -191,11 +193,15 @@ for p in seen_pkgs.keys(): uuid = genUID() # the submitter/user if muid == 0: - s = INSERT INTO Packages (ID, Name, Version, CategoryID, SubmittedTS, SubmitterUID, MaintainerUID) VALUES (%d, '%s', '%s', %d, %d, %d, NULL);\n % (seen_pkgs[p], p, genVersion(), - genCategory(), NOW, uuid) + s = (INSERT INTO Packages (ID, Name, Version, CategoryID, + SubmittedTS, SubmitterUID, MaintainerUID) VALUES + (%d, '%s', '%s', %d, %d, %d, NULL);\n) + s = s % (seen_pkgs[p], p, genVersion(), genCategory(), NOW, uuid) else: - s = INSERT INTO Packages (ID, Name, Version, CategoryID, SubmittedTS, SubmitterUID, MaintainerUID) VALUES (%d, '%s', '%s', %d, %d, %d, %d);\n % (seen_pkgs[p], p, genVersion(), - genCategory(), NOW, uuid, muid) + s = (INSERT INTO Packages (ID, Name, Version, CategoryID, + SubmittedTS, SubmitterUID, MaintainerUID) VALUES + (%d, '%s', '%s', %d, %d, %d, %d);\n) + s = s % (seen_pkgs[p], p, genVersion(), genCategory(), NOW, uuid, muid) out.write(s) count += 1 @@ -206,7 +212,9 @@ for p in seen_pkgs.keys(): for i in range(0, num_comments): fortune = commands.getoutput(FORTUNE_CMD).replace(',) now = NOW + random.randrange(400, 86400*3) - s = INSERT INTO PackageComments (PackageID, UsersID, Comments, CommentTS) VALUES (%d, %d, '%s', %d);\n % (seen_pkgs[p], genUID(), fortune, now) + s = (INSERT INTO PackageComments (PackageID, UsersID, + Comments, CommentTS) VALUES (%d, %d, '%s', %d);\n) + s = s % (seen_pkgs[p], genUID(), fortune, now) out.write(s) # Cast votes @@ -220,7 +228,9 @@ for u in user_keys: for v in range(num_votes): pkg = random.randrange(1, len(seen_pkgs) + 1) if not pkgvote.has_key(pkg): - s = INSERT INTO PackageVotes (UsersID, PackageID) VALUES (%d, %d);\n % (seen_users[u], pkg) + s = (INSERT INTO PackageVotes (UsersID, PackageID) + VALUES (%d, %d);\n) + s = s % (seen_users[u], pkg) pkgvote[pkg] = 1 if not track_votes.has_key(pkg): track_votes[pkg] = 0 @@ -230,7 +240,8 @@ for u in user_keys: # Update statements for package votes # for p in track_votes.keys(): - s = UPDATE Packages SET NumVotes = %d WHERE ID = %d;\n % (track_votes[p], p) + s = UPDATE Packages SET NumVotes = %d WHERE ID = %d;\n + s = s % (track_votes[p], p) out.write(s) # Create package dependencies and sources @@ -243,7 +254,8 @@ for p in seen_pkgs.keys(): while i != num_deps: dep = random.randrange(1, len(seen_pkgs) + 1) if not this_deps.has_key(dep): - s = INSERT INTO PackageDepends VALUES (%d, %d, NULL);\n % (seen_pkgs[p], dep) + s = INSERT INTO PackageDepends VALUES (%d, %d, NULL);\n + s = s % (seen_pkgs[p], dep) out.write(s) i += 1 @@ -255,8 +267,8 @@ for p in seen_pkgs.keys(): p, RANDOM_TLDS[random.randrange(0,len(RANDOM_TLDS))], RANDOM_LOCS[random.randrange(0,len(RANDOM_LOCS))], src_file, genVersion()) - s = INSERT INTO PackageSources VALUES (%d, '%s');\n % ( - seen_pkgs[p], src) + s = INSERT INTO PackageSources VALUES (%d, '%s');\n + s = s % (seen_pkgs[p], src) out.write(s) # close output file -- 1.7.4.1
Re: [aur-dev] some patches to gendummydata (take 3)
On Wed, Apr 6, 2011 at 7:23 PM, elij elij...@gmail.com wrote: Updated with changes Lukas requested. - split logging and mysql removal into separate patches - update logging patch with uppercase variable convention - drop tabs - spaces patch - clarified commit messages hmm. looks like I missed a single line extraction in my rebase -i for splitting the mysql and logging patches. +CATEGORIES_COUNT = 17 # the number of categories from aur-schema I can fix and resend if desired.
[aur-dev] some patches to gendummydata
Some patches for gendummydata script. - remove need for sql connection. this allows someone to run the script on a dev box with no sql connection (for example) and then ship the output sql wherever needed. - remove need to have category names. only the actual numbers are needed, and if you are using dummy data, you are likely using the base schema. even if that is not the case, as long as the base number of categories _at least_ are present, the dummy data is still 'fine' (eg. if more categories are added, then no dummy packages will just use those categories until the counter in the script is incremented) - use logging module - remove 'progress' logging output. the script doesn't run slow enough to warrant the extra noise - use spaces in the python script. spaces in python are _a damn good idea_
[aur-dev] [PATCH 2/4] make the formatting nicer and more readable
--- support/schema/gendummydata.py | 34 +++--- 1 files changed, 23 insertions(+), 11 deletions(-) diff --git a/support/schema/gendummydata.py b/support/schema/gendummydata.py index 47d9bd5..d424564 100755 --- a/support/schema/gendummydata.py +++ b/support/schema/gendummydata.py @@ -173,7 +173,9 @@ for u in user_keys: # pass - s = INSERT INTO Users (ID, AccountTypeID, Username, Email, Passwd) VALUES (%d, %d, '%s', '%s...@example.com', MD5('%s'));\n % (seen_users[u], account_type, u, u, u) + s = (INSERT INTO Users (ID, AccountTypeID, Username, Email, Passwd) + VALUES (%d, %d, '%s', '%s...@example.com', MD5('%s'));\n) +s = s % (seen_users[u], account_type, u, u, u) out.write(s) if count % 10 == 0: log.debug(working...) @@ -199,11 +201,15 @@ for p in seen_pkgs.keys(): uuid = genUID() # the submitter/user if muid == 0: - s = INSERT INTO Packages (ID, Name, Version, CategoryID, SubmittedTS, SubmitterUID, MaintainerUID) VALUES (%d, '%s', '%s', %d, %d, %d, NULL);\n % (seen_pkgs[p], p, genVersion(), - genCategory(), NOW, uuid) + s = (INSERT INTO Packages (ID, Name, Version, CategoryID, + SubmittedTS, SubmitterUID, MaintainerUID) VALUES + (%d, '%s', '%s', %d, %d, %d, NULL);\n) +s = s % (seen_pkgs[p], p, genVersion(), genCategory(), NOW, uuid) else: - s = INSERT INTO Packages (ID, Name, Version, CategoryID, SubmittedTS, SubmitterUID, MaintainerUID) VALUES (%d, '%s', '%s', %d, %d, %d, %d);\n % (seen_pkgs[p], p, genVersion(), - genCategory(), NOW, uuid, muid) + s = (INSERT INTO Packages (ID, Name, Version, CategoryID, + SubmittedTS, SubmitterUID, MaintainerUID) VALUES + (%d, '%s', '%s', %d, %d, %d, %d);\n) +s = s % (seen_pkgs[p], p, genVersion(), genCategory(), NOW, uuid, muid) out.write(s) if count % 100 == 0: @@ -216,7 +222,9 @@ for p in seen_pkgs.keys(): for i in range(0, num_comments): fortune = commands.getoutput(FORTUNE_CMD).replace(',) now = NOW + random.randrange(400, 86400*3) - s = INSERT INTO PackageComments (PackageID, UsersID, Comments, CommentTS) VALUES (%d, %d, '%s', %d);\n % (seen_pkgs[p], genUID(), fortune, now) + s = (INSERT INTO PackageComments (PackageID, UsersID, + Comments, CommentTS) VALUES (%d, %d, '%s', %d);\n) +s = s % (seen_pkgs[p], genUID(), fortune, now) out.write(s) # Cast votes @@ -231,7 +239,9 @@ for u in user_keys: for v in range(num_votes): pkg = random.randrange(1, len(seen_pkgs) + 1) if not pkgvote.has_key(pkg): - s = INSERT INTO PackageVotes (UsersID, PackageID) VALUES (%d, %d);\n % (seen_users[u], pkg) + s = (INSERT INTO PackageVotes (UsersID, PackageID) + VALUES (%d, %d);\n) +s = s % (seen_users[u], pkg) pkgvote[pkg] = 1 if not track_votes.has_key(pkg): track_votes[pkg] = 0 @@ -244,7 +254,8 @@ for u in user_keys: # Update statements for package votes # for p in track_votes.keys(): - s = UPDATE Packages SET NumVotes = %d WHERE ID = %d;\n % (track_votes[p], p) + s = UPDATE Packages SET NumVotes = %d WHERE ID = %d;\n +s = s % (track_votes[p], p) out.write(s) # Create package dependencies and sources @@ -258,7 +269,8 @@ for p in seen_pkgs.keys(): while i != num_deps: dep = random.randrange(1, len(seen_pkgs) + 1) if not this_deps.has_key(dep): - s = INSERT INTO PackageDepends VALUES (%d, %d, NULL);\n % (seen_pkgs[p], dep) + s = INSERT INTO PackageDepends VALUES (%d, %d, NULL);\n +s = s % (seen_pkgs[p], dep) out.write(s) i += 1 @@ -270,8 +282,8 @@ for p in seen_pkgs.keys(): p, RANDOM_TLDS[random.randrange(0,len(RANDOM_TLDS))], RANDOM_LOCS[random.randrange(0,len(RANDOM_LOCS))], src_file, genVersion()) - s = INSERT INTO PackageSources VALUES (%d, '%s');\n % ( - seen_pkgs[p], src) + s = INSERT INTO PackageSources VALUES (%d, '%s');\n +s = s % (seen_pkgs[p], src) out.write(s) if count % 100 == 0: -- 1.7.4.1
[aur-dev] [PATCH 3/4] reformat
- make the sql nicer and more readable - convert to spaces. who uses tabs in python!? --- support/schema/gendummydata.py | 248 1 files changed, 124 insertions(+), 124 deletions(-) diff --git a/support/schema/gendummydata.py b/support/schema/gendummydata.py index d424564..6ad4fb2 100755 --- a/support/schema/gendummydata.py +++ b/support/schema/gendummydata.py @@ -37,10 +37,10 @@ PKG_CMNTS = (1, 5) # min/max number of comments a package has CATEGORIES_COUNT = 17 # the number of categories from aur-schema VOTING= (0, .30) # percentage range for package voting RANDOM_PATHS = ( # random path locations for package files - /usr/bin, /usr/lib, /etc, /etc/rc.d, /usr/share, /lib, - /var/spool, /var/log, /usr/sbin, /opt, /usr/X11R6/bin, - /usr/X11R6/lib, /usr/libexec, /usr/man/man1, /usr/man/man3, - /usr/man/man5, /usr/X11R6/man/man1, /etc/profile.d +/usr/bin, /usr/lib, /etc, /etc/rc.d, /usr/share, /lib, +/var/spool, /var/log, /usr/sbin, /opt, /usr/X11R6/bin, +/usr/X11R6/lib, /usr/libexec, /usr/man/man1, /usr/man/man3, +/usr/man/man5, /usr/X11R6/man/man1, /etc/profile.d ) RANDOM_TLDS = (edu, com, org, net, tw, ru, pl, de, es) RANDOM_URL = (http://www.;, ftp://ftp.;, http://;, ftp://;) @@ -57,14 +57,14 @@ logging.basicConfig(format=logformat, level=level) log = logging.getLogger() if len(sys.argv) != 2: - log.error(Missing output filename argument) - raise SystemExit +log.error(Missing output filename argument) +raise SystemExit # make sure the seed file exists # if not os.path.exists(SEED_FILE): - log.error(Please install the 'words' Arch package) - raise SystemExit +log.error(Please install the 'words' Arch package) +raise SystemExit # track what users/package names have been used # @@ -75,16 +75,16 @@ user_keys = [] # some functions to generate random data # def genVersion(): - ver = [] - ver.append(%d % random.randrange(0,10)) - ver.append(%d % random.randrange(0,20)) - if random.randrange(0,2) == 0: - ver.append(%d % random.randrange(0,100)) - return ..join(ver) + -u%d % random.randrange(1,11) +ver = [] +ver.append(%d % random.randrange(0,10)) +ver.append(%d % random.randrange(0,20)) +if random.randrange(0,2) == 0: +ver.append(%d % random.randrange(0,100)) +return ..join(ver) + -u%d % random.randrange(1,11) def genCategory(): - return random.randrange(0,CATEGORIES_COUNT) +return random.randrange(0,CATEGORIES_COUNT) def genUID(): - return seen_users[user_keys[random.randrange(0,len(user_keys))]] +return seen_users[user_keys[random.randrange(0,len(user_keys))]] # load the words, and make sure there are enough words for users/pkgs @@ -94,25 +94,25 @@ fp = open(SEED_FILE, r) contents = fp.readlines() fp.close() if MAX_USERS len(contents): - MAX_USERS = len(contents) +MAX_USERS = len(contents) if MAX_PKGS len(contents): - MAX_PKGS = len(contents) +MAX_PKGS = len(contents) if len(contents) - MAX_USERS MAX_PKGS: - need_dupes = 0 +need_dupes = 0 else: - need_dupes = 1 +need_dupes = 1 # select random usernames # log.debug(Generating random user names...) user_id = USER_ID while len(seen_users) MAX_USERS: - user = random.randrange(0, len(contents)) - word = contents[user].replace(', ).replace(.,).replace( , _) - word = word.strip().lower() - if not seen_users.has_key(word): - seen_users[word] = user_id - user_id += 1 +user = random.randrange(0, len(contents)) +word = contents[user].replace(', ).replace(.,).replace( , _) +word = word.strip().lower() +if not seen_users.has_key(word): +seen_users[word] = user_id +user_id += 1 user_keys = seen_users.keys() # select random package names @@ -120,17 +120,17 @@ user_keys = seen_users.keys() log.debug(Generating random package names...) num_pkgs = PKG_ID while len(seen_pkgs) MAX_PKGS: - pkg = random.randrange(0, len(contents)) - word = contents[pkg].replace(', ).replace(.,).replace( , _) - word = word.strip().lower() - if not need_dupes: - if not seen_pkgs.has_key(word) and not seen_users.has_key(word): - seen_pkgs[word] = num_pkgs - num_pkgs += 1 - else: - if not seen_pkgs.has_key(word): - seen_pkgs[word] = num_pkgs - num_pkgs += 1 +pkg = random.randrange(0, len(contents)) +word = contents[pkg].replace(', ).replace(.,).replace( , _) +word = word.strip().lower() +if not need_dupes: +if not seen_pkgs.has_key(word) and not seen_users.has_key(word): +seen_pkgs[word] = num_pkgs +num_pkgs += 1 +else: +if not seen_pkgs.has_key(word): +seen_pkgs[word] = num_pkgs +
Re: [aur-dev] [PATCH 1/4] make gendummydata script more friendly
On Tue, Apr 5, 2011 at 6:58 PM, Dan McGee dpmc...@gmail.com wrote: On Tue, Apr 5, 2011 at 7:54 PM, elij elij...@gmail.com wrote: - no need to use mysql - just considering categories as an integer range, specified to the size of that in the aur-schema. - use logging module instead of writing directly to stderr this makes the code cleaner as there is only one test for the value of DBUG. Are we allergic to the letter 'E'? Sems slly to abreviate by one ltter, so why have it at all? Just set the logging level to DEBUG by default and anyone can tweak it to INFO if they feel so inclined. Fact. W ar allrgic to th lttr ' '. :P I didn't really even think about adding the missing E. I agree that if someone needs to edit the debug flag, they might as well just change the log var themselves. I thought about using optparse, but this script is so 'one off' that I wasn't sure it was worth the time to be honest. Yet...I still contributed patches for other things. ha!
Re: [aur-dev] [PATCH 3/4] reformat
On Tue, Apr 5, 2011 at 6:54 PM, Dan McGee dpmc...@gmail.com wrote: On Tue, Apr 5, 2011 at 7:54 PM, elij elij...@gmail.com wrote: - make the sql nicer and more readable - convert to spaces. who uses tabs in python!? -1. These should not be done in the same patch. -Dan They were both solely formatting changes, and changed no underlying logic or behavior. It seemed reasonable for me to include them both in the same patch.
[aur-dev] Some optimization patches
My apologies for splitting these changes into so many patches, but apparently the Arch mailman instance will not let anything larger than 40k though (and I got feedback that there is something amiss regarding the mailman setup -- this is here nor there though). These patches are mostly optimizations for content delivery. - merge css into fewer files to reduce number of files. this makes for faster end user delivery as there are fewer http requests (fewer tcp connections, whether the response is 200/ok or 304/not-modified). - created minimized versions of css. this reduced css size by 3.3K (24%) the originals are retained for ease of editing and reference - split out ie6 css into a separate file, and use 'conditional stylesheet inclusion' so that only ie6 fetches that stylesheet. - optimize logo png file -- this was a 22% (1K)
[aur-dev] [PATCH 2/7] add minified aur css
--- web/html/css/aur.min.css | 148 ++ 1 files changed, 148 insertions(+), 0 deletions(-) create mode 100644 web/html/css/aur.min.css diff --git a/web/html/css/aur.min.css b/web/html/css/aur.min.css new file mode 100644 index 000..51380bb --- /dev/null +++ b/web/html/css/aur.min.css @@ -0,0 +1,148 @@ +span{color:#555;font-family:Bitstream Vera Sans, Lucida Grande, Arial, sans-serif;} +span.f1{font-size:20px;letter-spacing:1px;} +span.f2{font-size:14px;color:#6c83b0;font-weight:bold;} +span.f3{color:#888;font-size:14px;font-weight:bold;padding-right:2px;} +span.f4{color:#444;font-size:12px;} +span.f5{color:#333;font-size:11px;} +span.f6{color:#b06d6e;font-size:14px;font-weight:bold;} +span.f7{color:#6db06d;font-size:14px;font-weight:bold;} +span.f8{color:#888;font-size:12px;font-weight:bold;} +span.fix{color:#000;font-family:monospace, fixed, terminal;font-size:12px;} +span.error{color:#900;font-size:12px;} +span.warning{color:#c0c000;font-size:12px;} +.blue{color:#6c83b0;} +.white{color:#fff;} +.black{color:#000;} +.green{color:#6db06d;} +.outofdate .blue{color:#444;} +.link{color:#6c83b0;font-weight:bold;} +span.preHeader{color:#c9d1e2;font-weight:bold;font-size:11px;padding-right:8px;word-spacing:8px;} +span.sideBarSmallHeader{color:#fff;font-weight:bold;font-size:11px;padding-right:8px;} +a{color:#0771a6;text-decoration:none;font-weight:bold;} +a:hover{color:#333;text-decoration:none;font-weight:bold;} +h1, h2, h3, h4{font-size:16pt;} +.important{font-weight:bold;color:#f00;} +body, table, td, img{border:none;margin:0;padding:0;} +td.preHeader{background-color:#000;border-bottom:1px solid #455471;height:16px;text-align:right;} +td.headerFill{background-color:#6c83b0;border-bottom:1px solid #000;} +td.headerDisplay{background-color:#6c83b0;padding-left:16px;} +td.mainLinks{background-color:#eee;border-bottom:1px solid #000;height:22px;padding-left:12px;} +td.sideBar{background-color:#fff;text-align:center;vertical-align:top;width:150px;} +td.sideBarGrey{background-color:#eee;border-bottom:1px solid #000;vertical-align:top;width:150px;} +td.sideBarSmall{background-color:#6c83b0;border-bottom:1px solid #000;height:16px;text-align:right;width:150px;} +td.sideBarSmallHeader{background-color:#6c83b0;vertical-align:top;height:16px;padding-top:1px;padding-bottom:2px;text-align:right;width:150px;} +td.subLinks{background-color:#ffe4e8;border-right:1px solid #000;color:#787878;padding-left:12px;height:19px;} +td.contentDisplay{background-color:#fff;border:1px solid #000;border-top:none;text-align:center;vertical-align:top;padding:10px;} +td.footerDisplay{background-color:#eee;border-bottom:1px solid #000;text-align:center;} +table.boxSoft{width:90%;background-color:#ddd;} +td.boxSoft{background-color:#fff;padding:2px;} +td.boxSoftColumn{padding-left:16px;padding-right:16px;text-align:justify;vertical-align:top;text-indent:20px;} +td.div{background-color:#eee;width:3px;} +.boxSoftTitle{border-bottom:1px solid #fff;border-top:1px solid #fff;background-color:#f1f2f4;padding:1px 0 0 3px;} +table.boxSoftSmall{width:94px;background-color:#ddd;} +td.boxSoftSmall{background-color:#fff;text-align:center;padding-top:2px;padding-bottom:2px;} +td.boxSoftSmallTitle{border-bottom:1px solid #ccc;background-color:#f1f2f4;padding-left:10px;} +td.ss{padding-left:6px;vertical-align:top;} +td.display{border-bottom:1px solid #000;padding-bottom:6px;} +td.features{padding:4px;text-align:justify;vertical-align:top;} +td.formLeft{padding:6px;vertical-align:top;} +td.data1{background-color:#eee;vertical-align:top;padding-left:.3em;} +td.data2{background-color:#ddd;vertical-align:top;padding-left:.3em;} +.outofdate{background-color:#faa;padding-left:.3em;} +.legend span{padding:1px;margin-left:.3em;border:solid 1px #888;} +td.text{color:#000;font-size:12px;} +th{text-align:left;} +th.header{border-bottom:#666 1px solid;vertical-align:bottom;} +fieldset{border:none;} +input, textarea, select{background-color:#6c83b0;font-family:monospace;font-size:12px;background-color:#ccc;border:#000 1px solid;color:#111;} +input.button{background-color:#fff;color:#6c83b0;border:1px solid #6c83b0;font-size:12px;padding:2px 8px;} +input[type=image]{border:0;background:none;}*{margin:0;padding:0;} +* ul{padding:20px;} +body{min-width:600px;background-color:white;color:#555;font-family:DejaVu Sans, sans-serif;font-size:12px;} +#title{display:block;position:relative;height:123px;} +#main_nav, #sub_nav{list-style:none;font-size:13px;line-height:26px;padding:0 32px;} +#main_nav{background-color:#333;text-align:right;} +#sub_nav{min-width:700px;background-color:#1793d1;text-align:right;} +#main_nav a.selected{background-color:#1793d1;} +#sub_nav a.selected{background-color:#333;} +#main_nav a, #sub_nav a{padding:5px 9px;line-height:26px;color:#fff;font-weight:bold;text-decoration:none;} +#main_nav a:hover{background-color:#1793d1;} +#sub_nav a:hover{background-color:#333;}
[aur-dev] [PATCH 4/7] split out the ie6 css into ie6 specific css file
--- web/html/css/archnavbar/archnavbar.css |6 +- web/html/css/archnavbar/ie6.css|2 ++ 2 files changed, 3 insertions(+), 5 deletions(-) create mode 100644 web/html/css/archnavbar/ie6.css diff --git a/web/html/css/archnavbar/archnavbar.css b/web/html/css/archnavbar/archnavbar.css index e8ade28..dd69382 100644 --- a/web/html/css/archnavbar/archnavbar.css +++ b/web/html/css/archnavbar/archnavbar.css @@ -10,11 +10,7 @@ #archnavbar { height: 40px !important; padding: 10px 15px !important; background: #333 !important; border-bottom: 5px #08c solid !important; } /* logo trickery -- GIF for IE6 and PNG for the rest */ -#archnavbarlogo { float: left !important; margin: 0 !important; padding: 0 !important; height: 40px !important; width: 190px !important; } -/* IE6 doesn't support alpha PNGs so we serve it a GIF */ -#archnavbarlogo { background: url('archlogo.gif') no-repeat !important; } -/* and use a proper PNG for all other modern browsers */ -html body #archnavbarlogo { background: url('archlogo.png') no-repeat !important; } +#archnavbarlogo { float: left !important; margin: 0 !important; padding: 0 !important; height: 40px !important; width: 190px !important; background: url('archlogo.png') no-repeat !important; } /* move the heading/paragraph text offscreen */ #archnavbarlogo p { margin: 0 !important; padding: 0 !important; text-indent: -px !important; } diff --git a/web/html/css/archnavbar/ie6.css b/web/html/css/archnavbar/ie6.css new file mode 100644 index 000..3f5b072 --- /dev/null +++ b/web/html/css/archnavbar/ie6.css @@ -0,0 +1,2 @@ +/* IE6 doesn't support alpha PNGs so we serve it a GIF */ +#archnavbarlogo { background: url('archlogo.gif') no-repeat !important; }
[aur-dev] [PATCH 3/7] add minified archnavbar css
--- web/html/css/archnavbar/archnavbar.min.css | 16 1 files changed, 16 insertions(+), 0 deletions(-) create mode 100644 web/html/css/archnavbar/archnavbar.min.css diff --git a/web/html/css/archnavbar/archnavbar.min.css b/web/html/css/archnavbar/archnavbar.min.css new file mode 100644 index 000..b4448cf --- /dev/null +++ b/web/html/css/archnavbar/archnavbar.min.css @@ -0,0 +1,16 @@ +#archnavbar{height:40px !important;padding:10px 15px !important;background:#333 !important;border-bottom:5px #08c solid !important;} +#archnavbarlogo{float:left !important;margin:0 !important;padding:0 !important;height:40px !important;width:190px !important;background:url('archlogo.png') no-repeat !important;} +#archnavbarlogo p{margin:0 !important;padding:0 !important;text-indent:-px !important;} +#archnavbarlogo h1{margin:0 !important;padding:0 !important;text-indent:-px !important;} +#archnavbarlogo a{display:block !important;height:40px !important;width:190px !important;} +#archnavbar ul{display:inline !important;float:right !important;list-style:none !important;margin:0 !important;padding:0 !important;} +#archnavbar ul li{float:left !important;font-size:14px !important;font-family:sans-serif !important;line-height:45px !important;padding-right:15px !important;padding-left:15px !important;} +#archnavbar ul#archnavbarlist li a{color:#999;font-weight:normal !important;text-decoration:none !important;} +#archnavbar ul li a:hover{color:white !important;text-decoration:underline !important;} +div#archdev-navbar{margin:1.5em 25px;} +div#archdev-navbar ul{list-style:none;margin:-0.5em 0;padding:0;} +div#archdev-navbar li{display:inline;margin:0;padding:0;font-size:0.9em;} +div#archdev-navbar li a{padding:0 0.5em;color:#07b;} +#archnavbar.anb-aur ul li#anb-aur a{color:white !important;} +#archnavbar ul#archnavbarlist li a{color:#999;font-weight:bold !important;text-decoration:none !important;} +#archnavbar ul li a:hover{color:white !important;text-decoration:underline !important;} \ No newline at end of file
[aur-dev] [PATCH 5/7] use new css files in header template
--- web/template/header.php |9 + 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/web/template/header.php b/web/template/header.php index 0f0e362..5862852 100644 --- a/web/template/header.php +++ b/web/template/header.php @@ -5,10 +5,11 @@ xml:lang=?php print $LANG\ lang=\$LANG; ? head titleAUR (?php print $LANG; ?)?php if ($title != ) { print - . $title; } ?/title - link rel='stylesheet' type='text/css' href='css/fonts.css' / - link rel='stylesheet' type='text/css' href='css/containers.css' / - link rel='stylesheet' type='text/css' href='css/arch.css' / - link rel='stylesheet' type='text/css' href='css/archnavbar/archnavbar.css' / + link rel='stylesheet' type='text/css' href='css/aur.min.css' / + link rel='stylesheet' type='text/css' href='css/archnavbar/archnavbar.min.css' / +!--[if IE 6] +link rel='stylesheet' type='text/css' href='css/archnavbar/ie6.css' / +![endif]-- link rel='shortcut icon' href='images/favicon.ico' / link rel='alternate' type='application/rss+xml' title='Newest Packages RSS' href='rss.php' / meta http-equiv=Content-Type content=text/html; charset=UTF-8 /
[aur-dev] [PATCH 7/7] specify dimensions for images
- some html renderers work faster/better if you specify image dimensions to avoid reflow/repaits --- web/template/stats/updates_table.php |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/template/stats/updates_table.php b/web/template/stats/updates_table.php index b9f6d6d..55ebf96 100644 --- a/web/template/stats/updates_table.php +++ b/web/template/stats/updates_table.php @@ -2,7 +2,7 @@ tr th colspan=2 class=boxSoftTitle style=text-align: right span class=f3?php print __(Recent Updates) ?span class=f5/span/span -a href=rss.phpimg src=images/feed-icon-14x14.png alt=RSS Feed //a +a href=rss.phpimg src=images/feed-icon-14x14.png width=14 height=14 alt=RSS Feed //a /th /tr @@ -23,7 +23,7 @@ $sub_int = intval($row[SubmittedTS]); if ($mod_int != 0): $modstring = gmdate(r, $mod_int); elseif ($sub_int != 0): - $modstring = 'img src=images/new.gif alt=New! / ' . gmdate(r, $sub_int); + $modstring = 'img src=images/new.gif width=31 height=12 alt=New! / ' . gmdate(r, $sub_int); else: $modstring = '(unknown)'; endif;
Re: [aur-dev] Some optimization patches
On Mon, Apr 4, 2011 at 2:20 PM, elij elij...@gmail.com wrote: My apologies for splitting these changes into so many patches, but apparently the Arch mailman instance will not let anything larger than 40k though (and I got feedback that there is something amiss regarding the mailman setup -- this is here nor there though). These patches are mostly optimizations for content delivery. - merge css into fewer files to reduce number of files. this makes for faster end user delivery as there are fewer http requests (fewer tcp connections, whether the response is 200/ok or 304/not-modified). - created minimized versions of css. this reduced css size by 3.3K (24%) the originals are retained for ease of editing and reference - split out ie6 css into a separate file, and use 'conditional stylesheet inclusion' so that only ie6 fetches that stylesheet. - optimize logo png file -- this was a 22% (1K) So, it looks like mailman gobbled my patches _again_ (3rd time was not a charm), saying 'a non text attachment was scrubbed' when the patches *are* text files (patch.txt). At this point I am giving up on sending them via the mailing list. If someone wants the patches, let me know and I will send them a tarball or post them somewhere.
Re: [aur-dev] Some optimzation patches
On Mon, Apr 4, 2011 at 2:30 PM, Lukas Fleischer archli...@cryptocrack.de wrote: On Sun, Apr 03, 2011 at 08:41:27PM -0700, elij wrote: Here are some patches that optimze a few things: - combine css for faster delivery (fewer tcp connections) - minimize css (faster delivery, bandwidth reduction) note: originals are retained for later editing and re-minimization - optimize png file - specific image dimensions in a few places where they were missing - move ie specific style (archnav bg image) to a separate stylesheet and include conditionally Seems like you forgot to submit a whole bunch of patches... I only got the PNG file optimization and the image dimension patches so far. I didn't forget. Mailman ate them. Aaron said there was something goofy going on with the mainman config. I will try submitting them _one last time_ using format-patch --inline instead of attach, and see if that makes a difference. Imho, we should also be careful with optimizing code for the sake of bandwidth reduction and speed. Most modern browsers have caching enabled by default, so most of those performance improvements will only come into operation once. I'll accept any patches as long as they don't have an impact on maintainability. Things like merging modular files into a single monster probably do. I guess it is up to you whether you want to include them or not. Caching is well and good if you have very long cache lifetimes. The aur appears to be configured for about 10 days into the future for expires headers. Also realize that to perform if-modified-since requests, the browser makes connections. Reducing the file counts (merging css files) reduces both tcp connections (whether response is 200 ok or 304 not modified) as well as wait time (waiting for responses for if-modified-since requests). Minimizing css files also reduces size.
[aur-dev] Some optimization patches
Trying to send these patches one final time, using 'inline' at Aaron's suggestion. Here goes. --- My apologies for splitting these changes into so many patches, but apparently the Arch mailman instance will not let anything larger than 40k though (and I got feedback that there is something amiss regarding the mailman setup -- this is here nor there though). These patches are mostly optimizations for content delivery. - merge css into fewer files to reduce number of files. this makes for faster end user delivery as there are fewer http requests (fewer tcp connections, whether the response is 200/ok or 304/not-modified). - created minimized versions of css. this reduced css size by 3.3K (24%) the originals are retained for ease of editing and reference - split out ie6 css into a separate file, and use 'conditional stylesheet inclusion' so that only ie6 fetches that stylesheet. - optimize logo png file -- this was a 22% (1K)
[aur-dev] [PATCH 2/7] add minified aur css
--- web/html/css/aur.min.css | 148 ++ 1 files changed, 148 insertions(+), 0 deletions(-) create mode 100644 web/html/css/aur.min.css diff --git a/web/html/css/aur.min.css b/web/html/css/aur.min.css new file mode 100644 index 000..51380bb --- /dev/null +++ b/web/html/css/aur.min.css @@ -0,0 +1,148 @@ +span{color:#555;font-family:Bitstream Vera Sans, Lucida Grande, Arial, sans-serif;} +span.f1{font-size:20px;letter-spacing:1px;} +span.f2{font-size:14px;color:#6c83b0;font-weight:bold;} +span.f3{color:#888;font-size:14px;font-weight:bold;padding-right:2px;} +span.f4{color:#444;font-size:12px;} +span.f5{color:#333;font-size:11px;} +span.f6{color:#b06d6e;font-size:14px;font-weight:bold;} +span.f7{color:#6db06d;font-size:14px;font-weight:bold;} +span.f8{color:#888;font-size:12px;font-weight:bold;} +span.fix{color:#000;font-family:monospace, fixed, terminal;font-size:12px;} +span.error{color:#900;font-size:12px;} +span.warning{color:#c0c000;font-size:12px;} +.blue{color:#6c83b0;} +.white{color:#fff;} +.black{color:#000;} +.green{color:#6db06d;} +.outofdate .blue{color:#444;} +.link{color:#6c83b0;font-weight:bold;} +span.preHeader{color:#c9d1e2;font-weight:bold;font-size:11px;padding-right:8px;word-spacing:8px;} +span.sideBarSmallHeader{color:#fff;font-weight:bold;font-size:11px;padding-right:8px;} +a{color:#0771a6;text-decoration:none;font-weight:bold;} +a:hover{color:#333;text-decoration:none;font-weight:bold;} +h1, h2, h3, h4{font-size:16pt;} +.important{font-weight:bold;color:#f00;} +body, table, td, img{border:none;margin:0;padding:0;} +td.preHeader{background-color:#000;border-bottom:1px solid #455471;height:16px;text-align:right;} +td.headerFill{background-color:#6c83b0;border-bottom:1px solid #000;} +td.headerDisplay{background-color:#6c83b0;padding-left:16px;} +td.mainLinks{background-color:#eee;border-bottom:1px solid #000;height:22px;padding-left:12px;} +td.sideBar{background-color:#fff;text-align:center;vertical-align:top;width:150px;} +td.sideBarGrey{background-color:#eee;border-bottom:1px solid #000;vertical-align:top;width:150px;} +td.sideBarSmall{background-color:#6c83b0;border-bottom:1px solid #000;height:16px;text-align:right;width:150px;} +td.sideBarSmallHeader{background-color:#6c83b0;vertical-align:top;height:16px;padding-top:1px;padding-bottom:2px;text-align:right;width:150px;} +td.subLinks{background-color:#ffe4e8;border-right:1px solid #000;color:#787878;padding-left:12px;height:19px;} +td.contentDisplay{background-color:#fff;border:1px solid #000;border-top:none;text-align:center;vertical-align:top;padding:10px;} +td.footerDisplay{background-color:#eee;border-bottom:1px solid #000;text-align:center;} +table.boxSoft{width:90%;background-color:#ddd;} +td.boxSoft{background-color:#fff;padding:2px;} +td.boxSoftColumn{padding-left:16px;padding-right:16px;text-align:justify;vertical-align:top;text-indent:20px;} +td.div{background-color:#eee;width:3px;} +.boxSoftTitle{border-bottom:1px solid #fff;border-top:1px solid #fff;background-color:#f1f2f4;padding:1px 0 0 3px;} +table.boxSoftSmall{width:94px;background-color:#ddd;} +td.boxSoftSmall{background-color:#fff;text-align:center;padding-top:2px;padding-bottom:2px;} +td.boxSoftSmallTitle{border-bottom:1px solid #ccc;background-color:#f1f2f4;padding-left:10px;} +td.ss{padding-left:6px;vertical-align:top;} +td.display{border-bottom:1px solid #000;padding-bottom:6px;} +td.features{padding:4px;text-align:justify;vertical-align:top;} +td.formLeft{padding:6px;vertical-align:top;} +td.data1{background-color:#eee;vertical-align:top;padding-left:.3em;} +td.data2{background-color:#ddd;vertical-align:top;padding-left:.3em;} +.outofdate{background-color:#faa;padding-left:.3em;} +.legend span{padding:1px;margin-left:.3em;border:solid 1px #888;} +td.text{color:#000;font-size:12px;} +th{text-align:left;} +th.header{border-bottom:#666 1px solid;vertical-align:bottom;} +fieldset{border:none;} +input, textarea, select{background-color:#6c83b0;font-family:monospace;font-size:12px;background-color:#ccc;border:#000 1px solid;color:#111;} +input.button{background-color:#fff;color:#6c83b0;border:1px solid #6c83b0;font-size:12px;padding:2px 8px;} +input[type=image]{border:0;background:none;}*{margin:0;padding:0;} +* ul{padding:20px;} +body{min-width:600px;background-color:white;color:#555;font-family:DejaVu Sans, sans-serif;font-size:12px;} +#title{display:block;position:relative;height:123px;} +#main_nav, #sub_nav{list-style:none;font-size:13px;line-height:26px;padding:0 32px;} +#main_nav{background-color:#333;text-align:right;} +#sub_nav{min-width:700px;background-color:#1793d1;text-align:right;} +#main_nav a.selected{background-color:#1793d1;} +#sub_nav a.selected{background-color:#333;} +#main_nav a, #sub_nav a{padding:5px 9px;line-height:26px;color:#fff;font-weight:bold;text-decoration:none;} +#main_nav a:hover{background-color:#1793d1;} +#sub_nav a:hover{background-color:#333;}
[aur-dev] [PATCH 6/7] optimize png file
- savings of about 1K (22%) --- web/html/css/archnavbar/archlogo.png | Bin 4192 - 3258 bytes 1 files changed, 0 insertions(+), 0 deletions(-) diff --git a/web/html/css/archnavbar/archlogo.png b/web/html/css/archnavbar/archlogo.png index e873e94b1a38b58963e15252f6e175fc1c6f1ec7..b4cf35f169d8e0848a62f2173ea8cfc0f2ba4e90 100644 GIT binary patch delta 3255 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 literal 4192 zcmV-m5TEafP)h;3K|Lk000e1NJLTq006!K001Zm1^@s6KubWw4b3#c}2nYxW zdbNS9a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^ zaAhuUa%Y?FJQ@H158X*bK~#90?VNjjRn?WpzxyO4+WI7toFEQXKzW1{6sdl6#-eR4 zw$nN~gI0@*en!)V8*$V!(+AZQ@$D$1i?6;S_*9yY-3U(@tmFsal^%a-bHj9_`( zfRCvtkL2d;`D2~?$hqgbMAxD();^-?kCAUd#}Auf4p^;ISrM0G9Fm31KfDw;b zy`JR1r;0wRF_#^45$IVSZ28uR8Ur^a#?)Sc18ey0IGnG#begCvIwrAf`b5~jIyo; zYLT}{tc-FisG#g9i^VrrwVu-IKgXr2N)HPS$j(sUO@#10p+sz7m`+bfMbCx%Ov~H z0Ve}TmP^N4|E?E?I{v%BA0uFYK2c2t?A8MEY+ywj*af@-oKjNM%!sMZ6{t^
[aur-dev] [PATCH 7/7] specify dimensions for images
- some html renderers work faster/better if you specify image dimensions to avoid reflow/repaits --- web/template/stats/updates_table.php |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/template/stats/updates_table.php b/web/template/stats/updates_table.php index b9f6d6d..55ebf96 100644 --- a/web/template/stats/updates_table.php +++ b/web/template/stats/updates_table.php @@ -2,7 +2,7 @@ tr th colspan=2 class=boxSoftTitle style=text-align: right span class=f3?php print __(Recent Updates) ?span class=f5/span/span -a href=rss.phpimg src=images/feed-icon-14x14.png alt=RSS Feed //a +a href=rss.phpimg src=images/feed-icon-14x14.png width=14 height=14 alt=RSS Feed //a /th /tr @@ -23,7 +23,7 @@ $sub_int = intval($row[SubmittedTS]); if ($mod_int != 0): $modstring = gmdate(r, $mod_int); elseif ($sub_int != 0): - $modstring = 'img src=images/new.gif alt=New! / ' . gmdate(r, $sub_int); + $modstring = 'img src=images/new.gif width=31 height=12 alt=New! / ' . gmdate(r, $sub_int); else: $modstring = '(unknown)'; endif;
[aur-dev] Some optimization patches
*sigh* Forgot to change the setting for format-patch and resent the same patches. Trying to send these patches one final time, using 'inline' at Aaron's suggestion. Here goes. --- My apologies for splitting these changes into so many patches, but apparently the Arch mailman instance will not let anything larger than 40k though (and I got feedback that there is something amiss regarding the mailman setup -- this is here nor there though). These patches are mostly optimizations for content delivery. - merge css into fewer files to reduce number of files. this makes for faster end user delivery as there are fewer http requests (fewer tcp connections, whether the response is 200/ok or 304/not-modified). - created minimized versions of css. this reduced css size by 3.3K (24%) the originals are retained for ease of editing and reference - split out ie6 css into a separate file, and use 'conditional stylesheet inclusion' so that only ie6 fetches that stylesheet. - optimize logo png file -- this was a 22% (1K)
[aur-dev] [PATCH 1/7] merge css files into one file
--- web/html/css/arch.css | 424 -- web/html/css/aur.css| 701 +++ web/html/css/containers.css | 188 web/html/css/fonts.css | 115 --- 4 files changed, 701 insertions(+), 727 deletions(-) delete mode 100644 web/html/css/arch.css create mode 100644 web/html/css/aur.css delete mode 100644 web/html/css/containers.css delete mode 100644 web/html/css/fonts.css diff --git a/web/html/css/arch.css b/web/html/css/arch.css deleted file mode 100644 index eec02ee..000 --- a/web/html/css/arch.css +++ /dev/null @@ -1,424 +0,0 @@ -* { margin: 0; padding: 0; } -* ul { padding: 20px; } -body { - min-width: 600px; - background-color: white; - color: #555; - font-family: DejaVu Sans, sans-serif; - font-size: 12px; -} -/* Divs */ -#title { - display: block; - position: relative; - height: 123px; -} -#main_nav, -#sub_nav { - list-style: none; - font-size: 13px; - line-height: 26px; - padding: 0 32px; -} -#main_nav { - background-color: #333; - text-align: right; -} -#sub_nav { - min-width: 700px; - background-color: #1793d1; - text-align: right; -} -#main_nav a.selected { - background-color: #1793d1; -} -#sub_nav a.selected { - background-color: #333; -} -#main_nav a, -#sub_nav a { - padding: 5px 9px; - line-height: 26px; - color: #fff; - font-weight: bold; - text-decoration: none; -} -#main_nav a:hover { - background-color: #1793d1; -} -#sub_nav a:hover { - background-color: #333; -} -#lang_sub { - display: block; - font-size: 10pt; - text-align: right; - margin-bottom: 40px; - margin-right: 35px; - margin-left: 35px; -} -#lang_sub ul { - list-style: none; - padding: 0px; -} -#lang_sub ul a { - text-decoration: none; -} -#lang_sub ul a:hover { - text-decoration: underline; -} -#lang_sub ul li { - display: inline; - padding-right: 1px; -} -#login_bar { - display: block; - margin-bottom: 10px; -} -#login_bar input { - margin-right: 5px; -} -#login_bar .button { - margin: 2px; -} -#updates { - font-size: small; - /*position: relative;*/ - top: 0px; - background-color: #e7f0f6; - border: 1px solid #92cbe8; - padding: 10px; -} -#logo { - z-index: 1; - position: relative; - top: 10px; - left: 25px; - width: 350px; -} -#logo h1#archtitle { - background: transparent url(../images/titlelogo.png) no-repeat top left; - margin: 0px; - padding: 0px; -} -#logo h1#archtitle a { - color: transparent; - display: block; - width: 350px; - height: 103px; -} -.clear { - clear: both; - margin: 0px; - padding: 0px; -} -.right { - float: right; - width: 320px; - padding: 0px 10px 10px 0px; -} -.left { - padding: 10px; - margin-right: 360px; -} -.left p { - padding-bottom: 10px; -} -.box { - padding: 10px; -} -.greybox { - padding: 10px; - background-color: #f6f3dd; - border: 1px solid #d9d6c2; -} -div.listing { - padding-right: 10px; -} -.error { - color: #dd; - font-size: small; -} -.foot { - clear: both; - text-align: center; - font-size: 0.75em; -} -#search { - float: right; - position: relative; - top: -2em; - font-size: 0.8em; -} -#search input { - background-color: #f6f3dd; - border: 1px solid #d9d6c2; -} -.smalltext { - text-align: right; - font-size: x-small; -} -/* Headers */ -h2 { - margin: 20px 0px 10px 0px; -} -h2.title { - border-bottom: 1px solid #46494d; -} -h3 { - margin-bottom: 10px; -} -h3.title { - text-align: right; - border-bottom: 1px solid #46494d; -} -h4.title { - border-bottom: 1px solid #46494d; -} -h4.news { - border-bottom: 1px dotted #0771a6; - margin-bottom: .25em; - padding-bottom: .2em; -} -div.listing h4 { - color: #fff; - background-color: #0771a6; - padding: 3px; -} -/* Paragraphs, Anchors, Images */ -p { - padding-bottom: 20px; -} -p.news { - font-size: small; -} -a { - color: #0771a6; -} -a:hover { - color: #333; -} -#about { - position: relative; - top: -9px; -} -ol { - padding-left: 45px; -} -ul.small { - list-style: none; - font-size: x-small; -} -ul.links { - list-style: none; - font-size: small; - padding: 0px 0px 20px 20px; -} -img { - border: none; -} -hr { - border: none; - border-top: 1px solid #46494d; -} -.greybox input, -button, -textarea, -select { - background-color: #e1e3e6; - border: 1px solid #8faecd; -} -.box input, button { - padding: 2px; - background-color: #c1c3f6; - font-size: x-small; - border: 1px solid #8faecd; -} -button#f_trigger { - background-color: #e1e3e6; -} -/* Table stuff */ -table.center { - margin-left: auto; - margin-right: auto; -} -table.results { - padding: 0px; - border-collapse: collapse; -} -.results th { - background-color: #e1e3e6; - border-bottom: 1px solid #46494d; - border-top: 1px solid #46494d; - padding: 0px 5px 0px 0px; -} -.results tha { - text-decoration: none; - color: #46494d; -} -.results td { - padding-right: 5px; - vertical-align: top; - font-size: 0.8em; -} -.listing th { - font-size: small; -
[aur-dev] [PATCH 3/7] add minified archnavbar css
--- web/html/css/archnavbar/archnavbar.min.css | 16 1 files changed, 16 insertions(+), 0 deletions(-) create mode 100644 web/html/css/archnavbar/archnavbar.min.css diff --git a/web/html/css/archnavbar/archnavbar.min.css b/web/html/css/archnavbar/archnavbar.min.css new file mode 100644 index 000..b4448cf --- /dev/null +++ b/web/html/css/archnavbar/archnavbar.min.css @@ -0,0 +1,16 @@ +#archnavbar{height:40px !important;padding:10px 15px !important;background:#333 !important;border-bottom:5px #08c solid !important;} +#archnavbarlogo{float:left !important;margin:0 !important;padding:0 !important;height:40px !important;width:190px !important;background:url('archlogo.png') no-repeat !important;} +#archnavbarlogo p{margin:0 !important;padding:0 !important;text-indent:-px !important;} +#archnavbarlogo h1{margin:0 !important;padding:0 !important;text-indent:-px !important;} +#archnavbarlogo a{display:block !important;height:40px !important;width:190px !important;} +#archnavbar ul{display:inline !important;float:right !important;list-style:none !important;margin:0 !important;padding:0 !important;} +#archnavbar ul li{float:left !important;font-size:14px !important;font-family:sans-serif !important;line-height:45px !important;padding-right:15px !important;padding-left:15px !important;} +#archnavbar ul#archnavbarlist li a{color:#999;font-weight:normal !important;text-decoration:none !important;} +#archnavbar ul li a:hover{color:white !important;text-decoration:underline !important;} +div#archdev-navbar{margin:1.5em 25px;} +div#archdev-navbar ul{list-style:none;margin:-0.5em 0;padding:0;} +div#archdev-navbar li{display:inline;margin:0;padding:0;font-size:0.9em;} +div#archdev-navbar li a{padding:0 0.5em;color:#07b;} +#archnavbar.anb-aur ul li#anb-aur a{color:white !important;} +#archnavbar ul#archnavbarlist li a{color:#999;font-weight:bold !important;text-decoration:none !important;} +#archnavbar ul li a:hover{color:white !important;text-decoration:underline !important;} \ No newline at end of file -- 1.7.4.1
[aur-dev] [PATCH 4/7] split out the ie6 css into ie6 specific css file
--- web/html/css/archnavbar/archnavbar.css |6 +- web/html/css/archnavbar/ie6.css|2 ++ 2 files changed, 3 insertions(+), 5 deletions(-) create mode 100644 web/html/css/archnavbar/ie6.css diff --git a/web/html/css/archnavbar/archnavbar.css b/web/html/css/archnavbar/archnavbar.css index e8ade28..dd69382 100644 --- a/web/html/css/archnavbar/archnavbar.css +++ b/web/html/css/archnavbar/archnavbar.css @@ -10,11 +10,7 @@ #archnavbar { height: 40px !important; padding: 10px 15px !important; background: #333 !important; border-bottom: 5px #08c solid !important; } /* logo trickery -- GIF for IE6 and PNG for the rest */ -#archnavbarlogo { float: left !important; margin: 0 !important; padding: 0 !important; height: 40px !important; width: 190px !important; } -/* IE6 doesn't support alpha PNGs so we serve it a GIF */ -#archnavbarlogo { background: url('archlogo.gif') no-repeat !important; } -/* and use a proper PNG for all other modern browsers */ -html body #archnavbarlogo { background: url('archlogo.png') no-repeat !important; } +#archnavbarlogo { float: left !important; margin: 0 !important; padding: 0 !important; height: 40px !important; width: 190px !important; background: url('archlogo.png') no-repeat !important; } /* move the heading/paragraph text offscreen */ #archnavbarlogo p { margin: 0 !important; padding: 0 !important; text-indent: -px !important; } diff --git a/web/html/css/archnavbar/ie6.css b/web/html/css/archnavbar/ie6.css new file mode 100644 index 000..3f5b072 --- /dev/null +++ b/web/html/css/archnavbar/ie6.css @@ -0,0 +1,2 @@ +/* IE6 doesn't support alpha PNGs so we serve it a GIF */ +#archnavbarlogo { background: url('archlogo.gif') no-repeat !important; } -- 1.7.4.1
[aur-dev] [PATCH 6/7] optimize png file
- savings of about 1K (22%) --- web/html/css/archnavbar/archlogo.png | Bin 4192 - 3258 bytes 1 files changed, 0 insertions(+), 0 deletions(-) diff --git a/web/html/css/archnavbar/archlogo.png b/web/html/css/archnavbar/archlogo.png index e873e94b1a38b58963e15252f6e175fc1c6f1ec7..b4cf35f169d8e0848a62f2173ea8cfc0f2ba4e90 100644 GIT binary patch delta 3255 zcmV;o3`q0fAi5clBYzBmNklZc-rlq3y7W8OINKoDzA4+r2x8fPlP2UP?eTViF5^ zDk$V6hhn67XoMJy8VVPzoY)H#;XBPvsSY0Z~AMF(IN!D0$q948ozQ4%T?Ne~c( z8hns+x=#*x3_1eXLfdr!kMan9Xs38Gu!j)p6~nmmer^jeq9rEo;=1M2H%oq+;n zLODKzzZ$e5XxKpC81Mo3JkWX2MNq4taRYr*z@H9^lI8`C8|bPBA3(1QILZ|0@N^Q z;6PV9_#+wUO-%|KSXwuM8u?XU(?u0cgEq|$_t0De-KnBXk?)}gQkJr03DCUx9;iI zn;+31hc-V3Dt}47KSsB(s+Z=j$RYAy-(mnBX=*Z|dHlk%d|nP2GC0RG}wy94Cr zzOJ*Y8o8KaeqkB9}e2yKkygZfWISXSc@(=!`v-B85d1cxiAyu0NAA%aAK*hH zHvyfo0Uy;RXy|N%uSJ43Mf#-9iT^*2MwK~m6-rP6o1jn;wFuz25pK@K;NK|1~I_ zpxJ^2va0RfF^=wf@XlmgNA|%T+~$`)Y{^^dLaA_g;zBA0DKI5=l}uS83G~I3I+L z(;5l*OMSj@j841{s*c)kmq9y0gDmQq48jzP1E32ajrKRC?{MsfNH3|N4ewsfEI# z1Ns2;cYjbNXbbHh18N`%epl*X13=@b1J41WL)s72Ocs1Jd3=Fm_Re|%_{q;13CbD z6GwB90%|*mEk)+$GzQbH3Sh~kH(e5o_YnCaB{WD3?0jNYICp=RQVHqFm;@E4VTX z=!tdIrk;zSb)cTs_eG1uznyQ+5N3vu4*1u^nd9grLvv5ucdnM+puqnAObWstZHlF zuK~IM`Y+V?JNP@dpscd9*tgi92hQ_YDD%9V`gjvZ;g?r!t%WlALixnR0q`QG~3 z2LBNTiYA1U*4{I#%#6^%4A0QE%HQ2k`#|`oiMaS!51v@_6npfVH_#Kq%~nPo zkbk=`h7u2F8cR6a|83l#S60!Z7FOdfx-Z9KpH;0ZbR5lL0Q(96ACUsSn9E2OO9go z7DkLt1Y@0$s=tmMEv21yWO$WN%!Qd#uHfqA5NAF`a;ks{|?7ThD#QWhMl6FPvFn z2;YZXJ-Xy^=RkQD(HJ+|(;WDpka^@~TYql}encyG03~tzGs5pQqfz%$bXvrgM9$g zv-wKJki4?0_MwP25JvpjuYS_z9v6n3`#b!^oJoddekBHFzBRBnd0V3_8!zP)TLj z+L71ho7dlB{-H+M0RJfoo8C%md;)(f=qu2BAdFd00SyLW==4qyrb`?Wz*0Pv41T1 zpM%~cGvsaw7%zdT70*hIq!1D2jMp~cNWvkE^0M(Jkgdk+lyw42zr?TMGD!ey0fz z9QRhtq*07RpYZA(Z*6**Q1}i_-xgOrUikaf(C3V+`h`5Dw{FN-1M!?H73) zEBJV^U3~z*1E?jyBpcu=!`xG8h=YE0qCHf6u@!^Q;%T*6q-9loH_A(i?Uyn|IiC` zEtM^#$kL}W(PU0JoxfE2a+Kr}J)zDNvyvRMhAxANfQq?S2?qX|Gsl3(ECWn#P zgtdjL-Bdf`8$YHQI^sAx*P)^%q(_)%OX03PoSUe%GvgZxeGSn)OdI4S)WeG@v)N z$p`S8gPx^mjMcW$VniR}0RBJ7!R60)QBW4awsYDWl3CW6+b;sDH1c5Vc=La;33 zIcK%_@PKefAgMzT|LwTmg;7+Cb)sGRE`)T=En*i%a#JQypdvSMya9;6=2%qXJK zUOAkbaqua6bH)eoam47A27mPVpsFN?E4(R|C!*NBL(F!{CS(l-yj12c86moID!wO zBen5zZvU1P@WFXZfNx_3pgl=M~-Su45GhkKj`#ONlD78yUKde30zfG5Lf`g~5* zSuzE_I3wq-u8IGh2#)MeFDEy@cjV6d8Y`y_ZJAFLScj1sX36zJF@0;KH15*n#g7 z);Rd8F_?Lx6q$f}0YCIgt;X4eocPMVOr-A#SW2`I6j0MvCc1eN=xB7rfLVV5({ z{NWzJpC3c-)Hb|aX98DZds`GC{JEb8a`MfUg?;%zNP`c`X6HQZb}9oS7Jj-GYC? z3H-dWs_QAmowzZ!Wq)k~3r@J+XXsHoU0y8SoHK%(zaLc0%xtyJw`EkC-4tQg1=Bu zZbp{Df7A(l7zr1~ZFX%Hm#+L9(;H@^i2nRIDS}d{l+M#R%gtK+#v2W+2q=!2No zit`Uy0Uu7*!}R1Ggp(h0LC=5=Ny7g_mu8O05p7~oz6+CTz+MTJb?eSpxo9p8ea6| zgI6FBhuhU^jA4UQYpE)xVnn-^Buz1o#nsIFl9npqZED68!W0bqPlNeCTAgkwit; z({XCufd7sJz!)daIk}aolbf7u{S2Gi~sQB-HB2k=ER#V06aKFJe~W@KyaK zN?CY~yB8Z%XMb*EQIk0M8#mT4ZdpJ$3%J_a0@;@WlU4YDn$XyP`U)AAJDl*(F+U z;5+zmk^vI%eu~Lzf@5(?dAG#z!(5m;r(8IgIEo#20KZBS{AL#6%=Hr2-JO|pNC*64 zY48HFqyIq~*maa%gzha$%POmdvL=K7p$J%uHD$A3i1f+~*k#d3)#6$0~m3QMbQ zsC95FhFH}-VZww?p!-ctnlz~u{O!$re~;6TlmU0LGEw}O(axbC)3btk|OLixxKi z5D(y^wp-L!Lh*XhF%N;x)0_f3fmLpiooV;m$2fu?(HGExJDEiNt(HhRNh)^d0qd zCctNMc7O2SR9Ch9e1JLIt49k;jovBeDb;U|g)QU1XNtCI*w+LsP6IO$F~CYoj7sg zX8a4F4+VWh=-Kdbo=H6QLg=UHg(ja93H27ek9poiUoXs20cz`1sHAlSWw2C`5esD z_puA`+gQw=niE;G$Z`HY=;wm$%`HrdvIu;qm49kQPT+$r|6$(bkHB6PDn+$Z|}8 z52HK-@xa8KfJ1VbnN=B9jE@rFbF;1!=o)PcsRUSVrINuyf1-@Fn#3UeHodFVJMr zI=lDe9FzdokZ7paBewDSmtrtgrPZrhoBmq8xEmpjD(wIXiPXqkX(%?t*b;cg zv41qWbk2O$U4dCh$-BKr%?^aGhJ+_*_*oHCtTG`qxMS^cx-%I?M~WWdyh9;lT z0jEiVk7mzws$C)sK73uk-^b^MXar4)*BniD~JGK2EanA9M*D-iUq7=XAhFz2Fgg zOqw%at++(+eP7;*hLl@i|e^K{u;9w12D3`++IG9%gPwS%tjeyJxIeW1gLk8; z3gsjZen_pnhoXp=?4BO@Td3nyTloka_^6ja#X|6*qHDvoDX2~=k!YwXHpgSK(Kyhw za6AV@cI25VG4kWcyhxD3%)avEpa}C$fVls0(yLZPKY^P1b!!nb3WiabF0l0fq#$A zZc37xqV+WIgPZVR?aZwn%m!OIJSbE;Ks4n1-9FewV#Foc=_U(xz7$!SNaW6YMg zmZ?slkfulTOwPZz;8s#1LcBRiYohsi%F;X@YMGIK$^%^g!M$bmh=!G4$)cJyVU zF*up^E;*uYIq)$o`3IV$Dz=#y5Pu0ndYdUMdXCH3#986B7AvNfF!?@MZXMO+ns9! zw?1GWmuZS4{-@TtUZ}*KH3%#avr%#5@aS-}T_!o@Y}QqRdJx`0h{kEAfn{OuL-G zuQ8olO2*ozsN+IC?twj!wM!ZMr*6*L9?jt9qBpPawWL=+uyuMBBdVdNB@(U8` zI)LowB6tj+wx*e5rzllVnyGEzqW*R?UR``M;+GArcO|ydE;g2UU;z{vO5l8%qy+v z5X;z%ql~p5%#dE{{Tnyc?a=pSR)hEkMC4z9;;0!$YC=OrOMO(C+O65wMp)T?Iv z)j==)jCaq0%b}ppale;6@QfYBv^8^Ru*)kI4EU40|ob7_395$_s8zplpG^#A2N+ zj@IaD`}V2{3YXqZouE1kuOkT*C4AFtpoRl1PnK#C*D5O7XasI4O+=9Qpe74V{n54 zWg7gA%8C3KCO#+W|UKPDza@Bo`=uiyhy$QDMX)X!$s{?eW#W2w|SHkrKx_ZI? pC8*z(c47G6hJv08Zc?C3=O_12)4A}qD=q*002ovPDHLkV1kQMK%oEt literal 4192 zcmV-m5TEafP)h;3K|Lk000e1NJLTq006!K001Zm1^@s6KubWw4b3#c}2nYxW zdbNS9a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^ zaAhuUa%Y?FJQ@H158X*bK~#90?VNjjRn?WpzxyO4+WI7toFEQXKzW1{6sdl6#-eR4 zw$nN~gI0@*en!)V8*$V!(+AZQ@$D$1i?6;S_*9yY-3U(@tmFsal^%a-bHj9_`( zfRCvtkL2d;`D2~?$hqgbMAxD();^-?kCAUd#}Auf4p^;ISrM0G9Fm31KfDw;b zy`JR1r;0wRF_#^45$IVSZ28uR8Ur^a#?)Sc18ey0IGnG#begCvIwrAf`b5~jIyo; zYLT}{tc-FisG#g9i^VrrwVu-IKgXr2N)HPS$j(sUO@#10p+sz7m`+bfMbCx%Ov~H z0Ve}TmP^N4|E?E?I{v%BA0uFYK2c2t?A8MEY+ywj*af@-oKjNM%!sMZ6{t^
[aur-dev] [PATCH 7/7] specify dimensions for images
- some html renderers work faster/better if you specify image dimensions to avoid reflow/repaits --- web/template/stats/updates_table.php |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/template/stats/updates_table.php b/web/template/stats/updates_table.php index b9f6d6d..55ebf96 100644 --- a/web/template/stats/updates_table.php +++ b/web/template/stats/updates_table.php @@ -2,7 +2,7 @@ tr th colspan=2 class=boxSoftTitle style=text-align: right span class=f3?php print __(Recent Updates) ?span class=f5/span/span -a href=rss.phpimg src=images/feed-icon-14x14.png alt=RSS Feed //a +a href=rss.phpimg src=images/feed-icon-14x14.png width=14 height=14 alt=RSS Feed //a /th /tr @@ -23,7 +23,7 @@ $sub_int = intval($row[SubmittedTS]); if ($mod_int != 0): $modstring = gmdate(r, $mod_int); elseif ($sub_int != 0): - $modstring = 'img src=images/new.gif alt=New! / ' . gmdate(r, $sub_int); + $modstring = 'img src=images/new.gif width=31 height=12 alt=New! / ' . gmdate(r, $sub_int); else: $modstring = '(unknown)'; endif; -- 1.7.4.1
[aur-dev] [PATCH 5/7] use new css files in header template
--- web/template/header.php |9 + 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/web/template/header.php b/web/template/header.php index 0f0e362..5862852 100644 --- a/web/template/header.php +++ b/web/template/header.php @@ -5,10 +5,11 @@ xml:lang=?php print $LANG\ lang=\$LANG; ? head titleAUR (?php print $LANG; ?)?php if ($title != ) { print - . $title; } ?/title - link rel='stylesheet' type='text/css' href='css/fonts.css' / - link rel='stylesheet' type='text/css' href='css/containers.css' / - link rel='stylesheet' type='text/css' href='css/arch.css' / - link rel='stylesheet' type='text/css' href='css/archnavbar/archnavbar.css' / + link rel='stylesheet' type='text/css' href='css/aur.min.css' / + link rel='stylesheet' type='text/css' href='css/archnavbar/archnavbar.min.css' / +!--[if IE 6] +link rel='stylesheet' type='text/css' href='css/archnavbar/ie6.css' / +![endif]-- link rel='shortcut icon' href='images/favicon.ico' / link rel='alternate' type='application/rss+xml' title='Newest Packages RSS' href='rss.php' / meta http-equiv=Content-Type content=text/html; charset=UTF-8 / -- 1.7.4.1
Re: [aur-dev] Some optimization patches
On Mon, Apr 4, 2011 at 2:44 PM, elij elij...@gmail.com wrote: *sigh* Forgot to change the setting for format-patch and resent the same patches. Trying to send these patches one final time, using 'inline' at Aaron's suggestion. Here goes. --- My apologies for splitting these changes into so many patches, but apparently the Arch mailman instance will not let anything larger than 40k though (and I got feedback that there is something amiss regarding the mailman setup -- this is here nor there though). These patches are mostly optimizations for content delivery. - merge css into fewer files to reduce number of files. this makes for faster end user delivery as there are fewer http requests (fewer tcp connections, whether the response is 200/ok or 304/not-modified). - created minimized versions of css. this reduced css size by 3.3K (24%) the originals are retained for ease of editing and reference - split out ie6 css into a separate file, and use 'conditional stylesheet inclusion' so that only ie6 fetches that stylesheet. - optimize logo png file -- this was a 22% (1K) Hooray! This time it worked.
Re: [aur-dev] various implementations of a json api query endpoint for the aur
On Sun, Mar 27, 2011 at 9:02 AM, Justin Davis jrc...@gmail.com wrote: Very cool! Are any of these implementations hosted anywhere? I have development versions running, but only the ruby version is 'live' right now. http://test.awesometrousers.net/ There is also a live-search implementation that utilizes the ruby backend: http://test.awesometrousers.net/search As the api supports limit and offset query variables, I have thought of making it the live-search also do load-on-scroll instead of load all at once, but I haven't endeavored to do so yet. I have been making an AUR scraper/copier that saves package meta-information. There is also a web service that provides the data. I put both the database and webservice here: http://juster.us/aurlite neat! I will take a look at it. This scraper saves the AUR data into a new schema as well as using SQLite so it has a slightly different angle than your projects. Because it is essentially read-only this works out well for my needs. I was not trying to mirror or re-implement the AUR. I was thinking of adding binary ALPM repos as well to provide a single service for searching/browsing packages across many repos as well as the AUR. This would probably have a javascript frontent much like your livesearch! Certainly feel free to re-use any of the livesearch code. It is liberally MIT licensed. :)
[aur-dev] various implementations of a json api query endpoint for the aur
Greetings. I have implemented stand-alone versions of the aur rpc interface, in 3 languages. https://github.com/cactus/spew-ruby (ruby + sinatra) https://github.com/cactus/spew-js (nodejs + coffee-script) https://github.com/cactus/spew-python (python + tornado) The ruby version is probably the most complete (and arguably my favorite of the 3 so far), but each is a usable implementation. The nodejs version may node be idiomatic node code, as I am still learning my way around that ecosystem. The python version dosen't have a good implementation of the '/search' livesearch example endpoint, but that is just due to laziness on my part (I could add it easily if anyone else was interested in it besides me). Currently all 3 versions utilize the mysql database format that the AUR itself uses. One nice aspect of having the rpc interface separated from the php aur code itself are: - less api endpoint downtime when performing maintenance on the aur - decoupled from the aur codebase which could provide an arena for faster development of new features for api clients - nicer languages to work with (I am not a fan of php, due to having used it extensively in the past ;). - ability to have a more restful interface (utilize http response codes: 404 for packages not found, 204 for no content, etc) - provides ability to version the api. this would be a way to support legacy clients for a while, after changes to the api. fake example: /api/v3/maint?q=bob - /api/v4/maintainer?q=bob The api I have currently implemented (v2) supports _search_ and _info_ type queries. Supporting _maintainer_ queries would be very easy to add to any of the implementations. The v2 interface is slightly different than the current rpc interface (more resftul, supports conditional get support for clients that can cache and perform conditional get requests -- to reduce bandwidth, etc). If there is any interest in utilizing any of the versions listed for Arch, I would be glad to continue working on the codebase and clean up any rough edges and add the maintainer feature. Creating an AUR query interface is one of the projects I use when learning a new language, so even if no version ever gets used for anything, I do not consider it a waste of my time -- so don't be concerned that I will feel bad if the answer is 'no'. Thanks.
Re: [aur-dev] Russian comments are '???'
On Fri, Feb 25, 2011 at 4:27 PM, Loui Chang louipc@gmail.com wrote: On Fri 25 Feb 2011 09:52 +0100, Lukas Fleischer wrote: On Fri, Feb 25, 2011 at 01:34:12PM +1000, Joker-jar wrote: Hi. Russian comments are like '???' now in the aur. Look: http://aur.archlinux.org/packages.php?ID=40365 I think, problem in database encoding Thanks, I'll look into that. Maybe you'd better create a bug report in the bug tracker, here. Anyways... Please write in English, only. AUR comments are public and should be readable and comprehensible for everyone. Not everyone understands English. ;) I had set the db to utf8 a long time ago but I guess something was changed in the upgrade steps. The schema doesn't explicitly set utf8, but maybe it should. Maybe the alter table to remove those unused columns? That would be a nice mysql gotcha -- if an alter table on unrelated columns changes the charset for other columns.
Re: [aur-dev] aur live-search
Fyi. The url changed (but the old url still redirects -- for now). New url: http://live.aursearch.net/ On Wed, Feb 9, 2011 at 4:16 PM, Loui Chang louipc@gmail.com wrote: On Thu 03 Feb 2011 22:37 -0800, elij wrote: I was messing around and created a live-search-like query interface (which utilizes the aur-rpc). forum post: https://bbs.archlinux.org/viewtopic.php?id=112878 example site: http://aurlivesearch.awesometrousers.net/ code: https://github.com/cactus/aurlivesearch Cool stuff man.
Re: [aur-dev] Question about sanitized data dumps
On Fri, Feb 4, 2011 at 3:29 PM, Loui Chang louipc@gmail.com wrote: Nothing has been set up yet, it's just something I had been thinking about. I think it could encourage more development. Yeah we would definitely have to sanitize the data. Providing the source packages via rsync or something would be the first step. I'm not too sure about MySQL data yet though. I see. Well if anything ever does develop in that regard, please send a copy my way! :)
[aur-dev] aur live-search
I was messing around and created a live-search-like query interface (which utilizes the aur-rpc). forum post: https://bbs.archlinux.org/viewtopic.php?id=112878 example site: http://aurlivesearch.awesometrousers.net/ code: https://github.com/cactus/aurlivesearch
[aur-dev] Question about sanitized data dumps
I have been [fooling around][1] with an aur-rpc reimplementation in ruby+redis with sphinx as the search engine. Loui [mentioned][2] he had been thinking about providing a dump of the existing database or something, to users who are interested in developing features and/or replacements. If so, and assuming the dump is sanitized in some way (remove real user email addresses, etc), I would certainly be interested. It would be nice to get some real data to play with. Is there any more information currently available on this? Thanks. [1]: https://github.com/cactus/spew-ruby [2]: http://mailman.archlinux.org/pipermail/aur-general/2011-January/013323.html
[aur-dev] moved my aurjson/rpc client examples
I refactored (slightly) and moved my aurjson/rpc example clients to a github repo. http://github.com/cactus/aurjson_examples When I first added/submitted the aurjson interface, I linked to some very basic reference clients. I simply moved those to github (after updating them slightly).
Re: [aur-dev] [PATCH] Add newly submitted packages functionality with json interface
I made a first run through refactoring the feed code, and throwing memcache in. I need to setup a php test machine to test and verify though... So it might take a little while for me to make that happen. That is, unless someone has an aur instance running that is willing to test my patches (and setup memcached and the requisite php module). ;) On Sat, Oct 10, 2009 at 7:55 AM, Dan McGee dpmc...@gmail.com wrote: On Thu, Oct 8, 2009 at 6:30 PM, elij elij...@gmail.com wrote: Well, if people can get memcached installed on the aur box, and it can be made a requirement for running the aur, then I would have no problem coding up a new rss class that returned rss2.0 _or_ json, based on a passed in parameter. This could wholly replace the existing rss2.php/rss.php mechanism. I don't think requiring memcached would be a bad idea; maybe make it just decoupled enough that people could still develop locally without it being necessary (fall back to no caching at all). I already added some caching changes [1] a while back that uses APC if it is available, but it would be trivial to just migrate everything to memcached and put in a generic caching layer/API. Now let me know when you want to move the DB off of MySQL, and we'll talk. :P -Dan [1] http://projects.archlinux.org/?p=aur.git;a=commitdiff;h=5d6f465170392861c0438723fa98efd4732d30ec;hp=92643bb8278f3f17d55e1e6c37210ddacb957dae
[aur-dev] Remove LocationID and return Category instead of CategoryID
Patch to update the aur data to return data a bit more 'friendly' to client side utilities. Additional query load should be minimal. Note: Removed LocationID from results because everything is unsupported now.
Re: [aur-dev] [PATCH] Add newly submitted packages functionality with json interface
Well, if people can get memcached installed on the aur box, and it can be made a requirement for running the aur, then I would have no problem coding up a new rss class that returned rss2.0 _or_ json, based on a passed in parameter. This could wholly replace the existing rss2.php/rss.php mechanism. I think adding alternate export types (json) to the rss mechanism makes more sense than adding rss logic to the rpc interface. Thoughts? (ooh. I am top-posting now.) On Thu, Oct 8, 2009 at 4:03 PM, Aaron Griffin aaronmgrif...@gmail.com wrote: On Thu, Oct 8, 2009 at 6:02 PM, elij elij...@gmail.com wrote: On Thu, Oct 8, 2009 at 3:36 PM, Aaron Griffin aaronmgrif...@gmail.com wrote: Flickr actually has two APIs - a feed based one and a REST based ajax API. Both accept a format=foo parameter and json is allowed for both sets. * Is the AUR's rss feed generated per request? Or is it a static output file? * If it's generated, why not simply use the same format= thing here. Note that Flickr finds it totally acceptable and ideal to use feeds in addition to their API As I recall, the feed is generated, then saved to a static file. This static file is then served up php script reads it to stdout if not expired, until such time as it expires. Then it is generated again. It appears to work that way as an artifact of the php class/import that is being used. There appears to be no option (without adding it yourself) to either use an alternate cache mechanism (memcached) or to return the feed in alternate formats (other than rss2.0). This is _mostly_ painting the shed though (or format war, tabs vs spaces, etc). Yet, for some reason this just doesn't 'smell' right to me though. I can be a bit conservative at times though. It just seems to me that, getting a list of the latest updates is .. wait for ... what feeds are for. Yes, exactly... but a feed doesn't always have to be RSS :)
Re: [aur-dev] aur-general: I no longer receive messages.
Yeah, I seem to recall phrakture banning html formatted emails in mailman. It DRASTICALLY cut down on the spam sent to lists. On Wed, Sep 30, 2009 at 1:59 PM, joz...@gmx.com wrote: On 30 Sep 2009 at 13:58, Loui Chang wrote: On Wed 30 Sep 2009 19:22 +0200, Xyne wrote: Can someone please check if there's anything wrong with my subscription to aur-general? I no longer recieve messages from the list. I've tried unsubscribing and resubscring and have checked my options as well. I even get confirmation emails when I post to the list. I don't think it's my email client (sylpheed) either as aur-dev and other lists still work as before (all of which use the same email account). I have checked my junk mail but there's nothing there (from Arch anyway). Any help would be appreciated. Thanks. Have you tried a different mail client? I'm not exactly sure who deals with the mailing lists but you might want to file a bug report at http://bugs.archlinux.org instead. Only time I can't see my messages is if I send them in HTML format. And since I'm using GMX, a coule of times it's happened because I tried to reply via webmail. The messages were blank because gmx.com still doesn't support plain text :) And I'm lazy to subscribe from another address. Jozsef Kurucity | Web Graphic Designer -- O ascii ribbon campaign - stop html mail - www.asciiribbon.org http://linux.sgms-centre.com/advocacy/no-ms-office.php
Re: [aur-dev] [PATCH 1/1] fix for FS#15947
On Mon, Sep 28, 2009 at 12:59 PM, Loui Chang louipc@gmail.com wrote: On Sun 27 Sep 2009 20:59 -0700, elij wrote: Fix for maintainer search ticket: FS#15947 Also http://mailman.archlinux.org/pipermail/aur-dev/2009-September/000892.html --- web/lib/aurjson.class.php | 41 ++--- 1 files changed, 34 insertions(+), 7 deletions(-) diff --git a/web/lib/aurjson.class.php b/web/lib/aurjson.class.php index 5b9ecd1..3af41be 100644 --- a/web/lib/aurjson.class.php +++ b/web/lib/aurjson.class.php @@ -95,10 +95,9 @@ class AurJSON { $keyword_string = mysql_real_escape_string($keyword_string, $this-dbh); $query = SELECT . implode(',', $this-fields) . - FROM Packages WHERE DummyPkg=0 AND ; - $query .= sprintf(( Name LIKE '%%%s%%' OR Description LIKE '%%%s%%' ), - $keyword_string, $keyword_string); - + FROM Packages, Users WHERE DummyPkg=0 AND . This line breaks the basic search function since ID from $fields is not unique. Why are you selecting from the Users table anyways? + ( Name LIKE '%{$keyword_string}%' OR . + Description LIKE '%{$keyword_string}%' ); $result = db_query($query, $this-dbh); if ( $result (mysql_num_rows($result) 0) ) { @@ -158,5 +157,33 @@ class AurJSON { return $this-json_error('No result found'); } } + + /** + * Returns all the packages for a specific maintainer. + * @param $maintainer The name of the maintainer. + * @return mixed Returns an array of value data containing the package data + **/ + private function msearch($maintainer) { + $maintainer = mysql_real_escape_string($maintainer, $this-dbh); + $fields = implode(',', $this-fields); + + $query = SELECT Users.Usermain as Maintainer, {$fields} . + FROM Packages, Users . + WHERE Packages.MaintainerUID = Users.UID AND . + Users.Username = '{$maintainer}'; Users.Usermain isn't a field in the database, neither is Users.UID. There's also the problem of ID from $fields not being unique. I've fixed all these and pushed the modified patch. Please test your patches! Thanks I didn't have a machine to test it on at the time. *shrug*
[aur-dev] fix for FS#15947
Rough cut of a fix for FS#15947. Another related request: http://mailman.archlinux.org/pipermail/aur-dev/2009-September/000892.html Laszlo's request also asked for 'submitter', but I think that is less useful, hence I left it out. It might make sense to add 'maintainer' to the info and search results. Unsure.
Re: [aur-dev] [PATCH 1/1] fix for FS#15947
Feel free to change it. -- elij (cactus) On Sun, Sep 27, 2009 at 9:14 PM, Loui Chang louipc@gmail.com wrote: On Sun 27 Sep 2009 20:59 -0700, elij wrote: Fix for maintainer search ticket: FS#15947 Also http://mailman.archlinux.org/pipermail/aur-dev/2009-September/000892.html Thanks. For future patch submissions please put a more descriptive subject, such as Add maintainer search to json interface. Closes FS#15947