[Collab-qa-commits] r681 - in wnpp: . images tables

sping-guest at alioth.debian.org sping-guest at alioth.debian.org
Tue Jan 29 19:32:07 UTC 2008


Author: sping-guest
Date: 2008-01-29 19:32:07 +0000 (Tue, 29 Jan 2008)
New Revision: 681

Added:
   wnpp/COPYING
   wnpp/config_inc.php5.dist
   wnpp/cron_shared.php5
   wnpp/cron_sync_list.php5
   wnpp/cron_sync_popcon.php5
   wnpp/images/
   wnpp/images/feed-icon.png
   wnpp/images/valid-rss-20.png
   wnpp/index.php5
   wnpp/news.php5
   wnpp/php.ini
   wnpp/popcon/
   wnpp/soap_test.php5
   wnpp/tables/
   wnpp/tables/table_structures.sql
Log:
Initial checkin of WNPP table web view and related scripts

Added: wnpp/COPYING
===================================================================
--- wnpp/COPYING	                        (rev 0)
+++ wnpp/COPYING	2008-01-29 19:32:07 UTC (rev 681)
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

Added: wnpp/config_inc.php5.dist
===================================================================
--- wnpp/config_inc.php5.dist	                        (rev 0)
+++ wnpp/config_inc.php5.dist	2008-01-29 19:32:07 UTC (rev 681)
@@ -0,0 +1,13 @@
+<?php
+
+$SERVER    = 'localhost';
+$DATABASE  = 'database';
+$USERNAME  = 'user';
+$PASSWORD  = 'password';
+
+$WNPP_TABLE = 'debian_wnpp';
+$POPCON_TABLE = 'debian_popcon';
+$LOG_INDEX_TABLE = 'debian_log_index';
+$LOG_MODS_TABLE = 'debian_log_mods';
+
+?>

Added: wnpp/cron_shared.php5
===================================================================
--- wnpp/cron_shared.php5	                        (rev 0)
+++ wnpp/cron_shared.php5	2008-01-29 19:32:07 UTC (rev 681)
@@ -0,0 +1,48 @@
+<?php
+
+function open_page() {
+    global $ENABLE_REFRESH_HEADER;
+    global $REFRESH_INTERVAL;
+
+    echo "<html>";
+    if ($ENABLE_REFRESH_HEADER) {
+        echo "<head>";
+        echo "<meta http-equiv=\"Refresh\" content=\"" . $REFRESH_INTERVAL . "; url=\">";
+        echo "</head>";
+    }
+    echo "<body>";
+    echo "<pre>\n";
+}
+
+function close_page() {
+    echo "\nDONE.\n";
+
+    echo "</pre>";
+    echo "</body>";
+    echo "</html>\n";
+}
+
+function check_run_allowed() {
+    global $ENABLE_GAP_CHECK;
+    global $LAST_RUN_FILENAME;
+    global $MINIMUM_RUN_GAP;
+
+    if (!$ENABLE_GAP_CHECK) {
+        return TRUE;
+    }
+
+    echo "CHECK TIME OF LAST RUN\n";
+    $atime = @fileatime($LAST_RUN_FILENAME);
+    if ($atime) {
+        $seconds_since_last_run = (time() - $atime);
+        if ($seconds_since_last_run < $MINIMUM_RUN_GAP) {
+            echo "  GAP TOO SMALL (come back in " . ($MINIMUM_RUN_GAP - $seconds_since_last_run) . " seconds)\n";
+            return FALSE;
+        }
+    }
+
+    touch($LAST_RUN_FILENAME);
+    return TRUE;
+}
+
+?>

Added: wnpp/cron_sync_list.php5
===================================================================
--- wnpp/cron_sync_list.php5	                        (rev 0)
+++ wnpp/cron_sync_list.php5	2008-01-29 19:32:07 UTC (rev 681)
@@ -0,0 +1,277 @@
+<?php
+/**
+ * Debian WNPP related PHP/MySQL Scripts
+ *
+ * Copyright (C) 2008 Sebastian Pipping
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Sebastian Pipping, webmaster at hartwork.org
+ */
+
+include("config_inc.php5");
+include("cron_shared.php5");
+
+$LAST_RUN_FILENAME = "__last_sync_list_run";
+$MINIMUM_RUN_GAP = 55;
+$ENABLE_GAP_CHECK = TRUE;
+
+$ENABLE_REFRESH_HEADER = FALSE;
+$REFRESH_INTERVAL = 60;
+$MAX_SOAP_QUERIES = 201;
+$TROUBLE_BLACKLIST = array(429035, 451077, 461925);
+
+
+$done_soap_queries = 0;
+
+function cleanup() {
+    global $link;
+
+    // Disconnect
+    echo "LOCAL DISCONNECT\n";
+    mysql_close($link);
+
+    close_page();
+}
+
+open_page();
+
+/*
+echo "BACK IN A FEW MINUTES\n";
+exit(0);
+*/
+
+if (!check_run_allowed()) {
+    close_page();
+    exit(0);
+}
+
+// Connect to database
+echo "LOCAL CONNECT\n";
+$link = mysql_connect($SERVER, $USERNAME, $PASSWORD);
+mysql_select_db($DATABASE);
+
+// Get all related bug numbers
+echo "REMOTE LIST\n";
+$PACKAGE = 'wnpp';
+try {
+    $done_soap_queries++;
+        $client = new SoapClient(NULL,
+                array('location'     => "http://bugs.debian.org/cgi-bin/soap.cgi",
+                'uri'     => "Debbugs/SOAP",
+                'proxy_host'  => "http://bugs.debian.org"));
+
+        $remote_idents = $client->__soapCall("get_bugs", array('package', $PACKAGE, 'status', 'open'));
+} catch (Exception $e) {
+    cleanup();
+    exit(0);
+}
+echo "  " . count($remote_idents) . " entries in remote database, " . count($TROUBLE_BLACKLIST) . " blacklisted\n";
+
+// Detect SQL injections
+foreach ($remote_idents as $i) {
+    if (!preg_match("/^\\d+$/", $i)) {
+        echo "INSECURE '$i'\n";
+        cleanup();
+        exit(0);
+    }
+}
+
+// Get all idents from database
+echo "LOCAL LIST\n";
+$result = mysql_query("SELECT ident FROM $WNPP_TABLE");
+$count = mysql_num_rows($result);
+$local_idents = array();
+for ($i = 0; $i < $count; $i++) {
+    $entry = mysql_fetch_row($result);
+    $ident = $entry[0];
+    array_push($local_idents, $ident);
+}
+echo "  " . count($local_idents) . " entries in local database\n";
+
+// Diff
+$local_only = array_diff($local_idents, $remote_idents);
+$count_local_only = count($local_only);
+$remote_only = array_diff(array_diff($remote_idents, $local_idents), $TROUBLE_BLACKLIST);
+$count_remote_only = count($remote_only);
+
+// Remove old bugs
+if ($count_local_only > 0) {
+    echo "LOCAL REMOVE\n";
+    $delete_set = implode(",", $local_only);
+
+    // Log entries
+    $query = "INSERT INTO $LOG_INDEX_TABLE (ident,type,project,description,event,event_stamp) "
+            . "SELECT ident,type,project,description,'CLOSE',NOW() "
+            . "FROM $WNPP_TABLE WHERE ident IN ($delete_set)";
+    $result = mysql_query($query);
+
+    // Delete entries
+    echo "  Removing $count_local_only entries\n";
+    echo "  {" . $delete_set . "}\n";
+    $query = "DELETE FROM $WNPP_TABLE WHERE ident IN ($delete_set)";
+    $result = mysql_query($query);
+}
+$local_only = array();
+
+
+function get_bug_soap($ident, $cur, $count, $isUpdate) {
+    global $client;
+    global $done_soap_queries;
+    global $WNPP_TABLE;
+    global $LOG_INDEX_TABLE;
+    global $LOG_MODS_TABLE;
+
+    echo "REMOTE QUERY [$cur/$count] " . ($isUpdate ? "UPDATE" : "ADD") . " $ident\n";
+    try {
+        $done_soap_queries++;
+        $bugresponse = $client->__soapCall("get_status", array('bug'=>$ident));
+    } catch (Exception $e) {
+        echo "  EXCEPTION\n";
+        return;
+    }
+    $bugobj = $bugresponse[$ident];
+
+    if (!preg_match("/^(IT[AP]|O|RF[AHP]): ([^ ]+) -- (.+)$/", $bugobj->subject, $matches)) {
+        echo "  FORMAT ERROR\n";
+        return;
+    }
+
+    $mod_stamp = mysql_real_escape_string($bugobj->log_modified);
+    $type = $matches[1];
+    $project = mysql_real_escape_string($matches[2]);
+    $description = mysql_real_escape_string($matches[3]);
+    $charge_person = mysql_real_escape_string($bugobj->owner);
+
+    if ($isUpdate) {
+        // Get current state
+        $condition = "ident = '" . mysql_real_escape_string($ident) . "'";
+        $query = "SELECT *,UNIX_TIMESTAMP(open_stamp) as unix_open_stamp FROM $WNPP_TABLE WHERE $condition";
+        $result = mysql_query($query);
+        $count = mysql_num_rows($result);
+        if ($count != 1) {
+            return;
+        }
+        $entry = mysql_fetch_assoc($result);
+
+        // Compare
+        $old_mod_stamp = $entry['unix_open_stamp'];
+        $old_type = $entry['type'];
+        $old_project = mysql_real_escape_string($entry['project']);
+        $old_description = mysql_real_escape_string($entry['description']);
+        $old_charge_person = mysql_real_escape_string($entry['charge_person']);
+
+        $changes = array();
+        if ($mod_stamp != $old_mod_stamp) {
+            array_push($changes, "mod_stamp=FROM_UNIXTIME($mod_stamp)");
+        }
+        $type_changed = ($type != $old_type);
+        if ($type_changed) {
+            array_push($changes, "type='$type'");
+            echo "  TYPE set from [$old_type] to [$type]\n";
+        }
+        if ($project != $old_project) {
+            array_push($changes, "project='$project'");
+            echo "  PROJECT set from [$old_project] to [$project]\n";
+        }
+        if ($description != $old_description) {
+            array_push($changes, "description='$description'");
+        }
+        if ($charge_person != $old_charge_person) {
+            array_push($changes, "charge_person='$charge_person'");
+            echo "  OWNER set from [" . htmlspecialchars($old_charge_person)
+                    . "] to [" . htmlspecialchars($charge_person) . "]\n";
+        }
+
+        // Update state
+/*
+        if (true) { // TODO Remove once filled, originator won't change
+            $open_person = mysql_real_escape_string($bugobj->originator);
+            array_push($changes, "open_person='$open_person'");
+        }
+*/
+        array_push($changes, "cron_stamp=NOW()");
+        $updates = implode(", ", $changes);
+        $query = "UPDATE $WNPP_TABLE SET $updates WHERE $condition";
+        $result = mysql_query($query);
+
+        if ($type_changed) {
+            // Log entry
+            $query = "INSERT INTO $LOG_INDEX_TABLE (ident,type,project,description,event,event_stamp) "
+                    . "SELECT ident,type,project,description,'MOD',FROM_UNIXTIME($mod_stamp) FROM $WNPP_TABLE WHERE "
+                    . "ident = '$ident'";
+            $result = mysql_query($query);
+
+            // Log details
+            $query = "INSERT INTO $LOG_MODS_TABLE (log_id,before_type,after_type) "
+                    . "VALUES "
+                    . "(LAST_INSERT_ID(),'$old_type','$type')";
+            $result = mysql_query($query);
+        }
+    } else {
+        // Add
+        $open_person = mysql_real_escape_string($bugobj->originator);
+        $open_stamp = mysql_real_escape_string($bugobj->date);
+        echo "  [$ident][$type][$project][$description]\n";
+
+        // Bug data
+        $query = "INSERT INTO $WNPP_TABLE (ident,open_person,open_stamp,mod_stamp,type,project,description,charge_person) "
+                . "VALUES "
+                . "($ident,'$open_person',FROM_UNIXTIME(${open_stamp}),FROM_UNIXTIME(${mod_stamp}),'$type',"
+                . "'$project','$description','$charge_person')";
+        $result = mysql_query($query);
+
+        // Log entry
+        $query = "INSERT INTO $LOG_INDEX_TABLE (ident,type,project,description,event,event_stamp) "
+                . "SELECT ident,type,project,description,'OPEN',open_stamp FROM $WNPP_TABLE WHERE "
+                . "ident = '$ident'";
+        $result = mysql_query($query);
+
+        echo "  ADDED\n";
+    }
+}
+
+// Add new bugs
+if ($count_remote_only > 0) {
+    echo "LOCAL ADD\n";
+    echo "  Adding $count_remote_only entries\n";
+    $entries_to_grab = min($MAX_SOAP_QUERIES - $done_soap_queries, $count_remote_only);
+    for ($i = 0; $i < $entries_to_grab; $i++) {
+        $ident = array_pop($remote_only);
+        get_bug_soap($ident, $i + 1, $entries_to_grab, FALSE);
+    }
+}
+
+// Update existing bugs
+echo "LOCAL UPDATE\n";
+$entries_to_update = $MAX_SOAP_QUERIES - $done_soap_queries;
+$query = "SELECT ident FROM $WNPP_TABLE ORDER BY cron_stamp ASC LIMIT $entries_to_update";
+$result = mysql_query($query);
+$entries_to_update = mysql_num_rows($result);
+
+if ($entries_to_update > 0) {
+    echo "  Checking " . $entries_to_update . " entries for updates\n";
+
+    for ($i = 0; $i < $entries_to_update; $i++) {
+        $entry = mysql_fetch_row($result);
+        $ident = $entry[0];
+        get_bug_soap($ident, $i + 1, $entries_to_update, TRUE);
+    }
+}
+
+cleanup();
+exit(0);
+
+?>

Added: wnpp/cron_sync_popcon.php5
===================================================================
--- wnpp/cron_sync_popcon.php5	                        (rev 0)
+++ wnpp/cron_sync_popcon.php5	2008-01-29 19:32:07 UTC (rev 681)
@@ -0,0 +1,136 @@
+<?php
+/**
+ * Debian WNPP related PHP/MySQL Scripts
+ *
+ * Copyright (C) 2008 Sebastian Pipping
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Sebastian Pipping, webmaster at hartwork.org
+ */
+
+include("config_inc.php5");
+include("cron_shared.php5");
+
+
+$LAST_RUN_FILENAME = "__last_sync_popcon_run";
+$MINIMUM_RUN_GAP = 60 * 60 * 12; // 12 hours
+$ENABLE_GAP_CHECK = TRUE;
+
+$KEEP_FILES = 4;
+
+
+
+$POPCON_URL = "http://popcon.debian.org/source/by_inst.gz";
+$POPCON_DIR = "popcon";
+$POPCON_LOCAL = "${POPCON_DIR}/pkg_by_inst_" . date("Ymd_His"). ".gz";
+
+
+open_page();
+
+if (!check_run_allowed()) {
+    close_page();
+    exit(0);
+}
+
+// Download
+echo "REMOTE READ\n";
+$online_file = @file_get_contents($POPCON_URL);
+if (empty($online_file)) {
+    echo "  ERROR\n";
+    close_page();
+    exit(0);
+}
+echo "  SUCCESS\n";
+
+// Ensure directory presence
+ at mkdir($POPCON_DIR, 0750);
+
+// Remove old files
+$old_files = glob("${POPCON_DIR}/pkg_by_inst_????????_??????.gz");
+$count_old_files = count($old_files);
+$rem_files = max(0, $count_old_files - $KEEP_FILES);
+if ($rem_files > 0) {
+    echo "LOCAL DELETE\n";
+    for ($i = 1; $i <= $rem_files; $i++) {
+        $file_to_delete = $old_files[$i];
+        echo "  [$i/$rem_files] $file_to_delete\n";
+        unlink($file_to_delete);
+    }
+}
+
+// Write to file
+echo "LOCAL WRITE\n";
+$FILE = @fopen($POPCON_LOCAL, "w");
+if ($FILE) {
+    $written_bytes = @fwrite($FILE, $online_file);
+    @fclose($FILE);
+    echo "  SUCCESS\n";
+} else {
+    echo "  ERROR\n";
+}
+
+function cleanup() {
+    global $link;
+
+    // Disconnect
+    echo "LOCAL DISCONNECT\n";
+    mysql_close($link);
+
+    close_page();
+}
+
+// Connect to database
+echo "LOCAL CONNECT\n";
+$link = mysql_connect($SERVER, $USERNAME, $PASSWORD);
+mysql_select_db($DATABASE);
+
+// Reading local file
+echo "LOCAL READ\n";
+$GZ_FILE = gzopen($POPCON_LOCAL, "rb");
+$matches = array();
+if ($GZ_FILE) {
+    for (;;) {
+        $line = gzgets($GZ_FILE);
+        if (!$line) {
+            if (!gzeof($GZ_FILE)) {
+                echo "  ERROR\n";
+            }
+            break;
+        }
+
+        if (!preg_match("/^\\d+\s+(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+[\r\n]+$/", $line, $matches)) {
+            continue;
+        }
+
+        $package = mysql_real_escape_string($matches[1]);
+        $inst = mysql_real_escape_string($matches[2]);
+        $vote = mysql_real_escape_string($matches[3]);
+        $old = mysql_real_escape_string($matches[4]);
+        $recent = mysql_real_escape_string($matches[5]);
+        $nofiles = mysql_real_escape_string($matches[6]);
+
+        echo "  [$package][$inst][$vote][$old][$recent][$nofiles]\n";
+        $query = "INSERT INTO $POPCON_TABLE (package,inst,vote,old,recent,nofiles) VALUES "
+                . "('$package',$inst,$vote,$old,$recent,$nofiles) ON DUPLICATE KEY UPDATE "
+                . "inst=$inst,vote=$vote,old=$old,recent=$recent,nofiles=$nofiles";
+        $result = mysql_query($query);
+    }
+    gzclose($GZ_FILE);
+}
+
+cleanup();
+
+?>

Added: wnpp/images/feed-icon.png
===================================================================
(Binary files differ)


Property changes on: wnpp/images/feed-icon.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: wnpp/images/valid-rss-20.png
===================================================================
(Binary files differ)


Property changes on: wnpp/images/valid-rss-20.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: wnpp/index.php5
===================================================================
--- wnpp/index.php5	                        (rev 0)
+++ wnpp/index.php5	2008-01-29 19:32:07 UTC (rev 681)
@@ -0,0 +1,689 @@
+<?php
+/**
+ * Debian WNPP related PHP/MySQL Scripts
+ *
+ * Copyright (C) 2008 Sebastian Pipping
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Sebastian Pipping, webmaster at hartwork.org
+ */
+
+// MySQL >=4.1.x required
+
+include("config_inc.php5");
+
+$TITLE = "Debian Packages that Need Lovin'";
+$MAX_PROJECT_LEN = 20;
+$MAX_DESCR_LEN = 60;
+
+
+// Get order settings
+function other_direction_lower($dir) {
+    return ($dir == "ASC") ? "desc" : "asc";
+}
+
+function to_order_col($user_col) {
+    switch ($user_col) {
+    case "dust": return "mod_stamp";
+    case "age": return "open_stamp";
+    case "users": return "vote";
+    case "installs": return "inst";
+    case "owner": return "charge_person";
+    case "reporter": return "open_person";
+    default: return $user_col;
+    }
+}
+
+function get_sort_part_for_column($user_col) {
+    global $order_col;
+    global $order_dir;
+
+    switch ($user_col) {
+    case "age": // FALLTRHOUGH
+    case "dust":
+        return "sort=$user_col;" . (($order_col == to_order_col($user_col))
+                ? strtolower($order_dir)
+                : "asc");
+    default:
+        return "sort=$user_col;" . (($order_col == to_order_col($user_col))
+                ? other_direction_lower($order_dir)
+                : "asc");
+    }
+}
+
+if (empty($_GET['sort'])) {
+    $_GET['sort'] = "project";
+}
+$matches = array();
+if (!preg_match("/^(dust|age|type|project|users|installs|owner|reporter)(?:;((?:a|de)sc))?$/", $_GET['sort'], $matches)) {
+    $order_col = 'project';
+    $order_dir = 'ASC';
+} else {
+    $order_col = to_order_col($matches[1]);
+    $order_dir = ($matches[2] == "") ? "ASC" : strtoupper($matches[2]);
+
+    // Age must be inverted, proper column name
+    switch ($order_col) {
+    case "open_stamp": // FALLTROUGH
+    case "mod_stamp": // FALLTROUGH
+        $order_dir = ($order_dir == "ASC") ? "DESC" : "ASC";
+        break;
+    } 
+}
+$sort_part = "sort=" . urlencode($_GET['sort']);
+
+
+
+// Get owner settings
+$with_owner = FALSE;
+$without_owner = FALSE;
+
+if (isset($_GET['owner'])) {
+    foreach($_GET['owner'] as $owner) {
+        switch ($owner) {
+        case "yes": $with_owner = TRUE; break;
+        case "no": $without_owner = TRUE; break;
+        }
+    }
+}
+
+$owners = array();
+if ($with_owner) { array_push($owners, "yes"); }
+if ($without_owner) { array_push($owners, "no"); }
+
+if (empty($owners)) {
+    $owner_match = '1';
+    $owner_uri_part = '';
+
+    $with_owner = TRUE;
+    $without_owner = TRUE;
+} else {
+    if ($with_owner && $without_owner) {
+        $owner_match = '1';
+        $owner_uri_part = '';
+    } else {
+        $OWNER_KEY = to_order_col('owner');
+        if ($with_owner) {
+            $owner_match = "(($OWNER_KEY IS NOT NULL) AND ($OWNER_KEY != ''))";
+            $owner_uri_part = 'owner%5B%5D=yes&';
+        } else {
+            $owner_match = "(($OWNER_KEY IS NULL) OR ($OWNER_KEY = ''))";
+            $owner_uri_part = 'owner%5B%5D=no&';
+        }
+    }
+}
+
+
+
+// Get type settings
+$show_ita = FALSE;
+$show_itp = FALSE;
+$show_o = FALSE;
+$show_rfa = FALSE;
+$show_rfh = FALSE;
+$show_rfp = FALSE;
+
+if (isset($_GET['type'])) {
+    foreach($_GET['type'] as $type) {
+        switch ($type) {
+        case "ITA": $show_ita = TRUE; break;
+        case "ITP": $show_itp = TRUE; break;
+        case "O":   $show_o   = TRUE; break;
+        case "RFA": $show_rfa = TRUE; break;
+        case "RFH": $show_rfh = TRUE; break;
+        case "RFP": $show_rfp = TRUE; break;
+        }
+    }
+}
+
+$types = array();
+if ($show_ita) { array_push($types, "ITA"); }
+if ($show_itp) { array_push($types, "ITP"); }
+if ($show_o  ) { array_push($types, "O"  ); }
+if ($show_rfa) { array_push($types, "RFA"); }
+if ($show_rfh) { array_push($types, "RFH"); }
+if ($show_rfp) { array_push($types, "RFP"); }
+
+$DEFAULT_SHOW_ITA = FALSE;
+$DEFAULT_SHOW_ITP = FALSE;
+$DEFAULT_SHOW_O = TRUE;
+$DEFAULT_SHOW_RFA = TRUE;
+$DEFAULT_SHOW_RFH = TRUE;
+$DEFAULT_SHOW_RFP = TRUE;
+
+if (empty($types)) {
+    $type_match = 'type NOT IN (\'ita\',\'itp\')';
+    $type_uri_part = '';
+
+    $show_ita = $DEFAULT_SHOW_ITA;
+    $show_itp = $DEFAULT_SHOW_ITP;
+    $show_o = $DEFAULT_SHOW_O;
+    $show_rfa = $DEFAULT_SHOW_RFA;
+    $show_rfh = $DEFAULT_SHOW_RFH;
+    $show_rfp = $DEFAULT_SHOW_RFP;
+} else {
+    if (($show_ita == $DEFAULT_SHOW_ITA)
+            && ($show_itp == $DEFAULT_SHOW_ITP)
+            && ($show_o == $DEFAULT_SHOW_O)
+            && ($show_rfa == $DEFAULT_SHOW_RFA)
+            && ($show_rfh == $DEFAULT_SHOW_RFH)
+            && ($show_rfp == $DEFAULT_SHOW_RFP)) {
+        $type_uri_part = '';
+    } else {
+        $type_uri_part = "type%5B%5D=" . implode("&type%5B%5D=", $types) . "&";
+    }
+
+    if (count($types) == 6) { // XXX
+        $type_match = '1';
+    } else {
+        $type_match = "type IN ('" . implode("','", $types) . "')";
+    }
+}
+
+
+
+// Get col settings
+$show_dust = FALSE;
+$show_age = FALSE;
+$show_type = FALSE;
+$show_description = FALSE;
+$show_users = FALSE;
+$show_installs = FALSE;
+$show_owner = FALSE;
+$show_reporter = FALSE;
+
+if (isset($_GET['col'])) {
+    foreach($_GET['col'] as $col) {
+        switch ($col) {
+        case "dust": $show_dust = TRUE; break;
+        case "age": $show_age = TRUE; break;
+        case "type": $show_type = TRUE; break;
+        case "description": $show_description = TRUE; break;
+        case "users": $show_users = TRUE; break;
+        case "installs": $show_installs = TRUE; break;
+        case "owner": $show_owner = TRUE; break;
+        case "reporter": $show_reporter = TRUE; break;
+        }
+    }
+}
+
+$cols = array();
+if ($show_dust) { array_push($cols, "dust"); }
+if ($show_age) { array_push($cols, "age"); }
+if ($show_type) { array_push($cols, "type"); }
+if ($show_description) { array_push($cols, "description"); }
+if ($show_users) { array_push($cols, "users"); }
+if ($show_installs) { array_push($cols, "installs"); }
+if ($show_owner) { array_push($cols, "owner"); }
+if ($show_reporter) { array_push($cols, "reporter"); }
+
+
+$DEFAULT_SHOW_DUST = TRUE;
+$DEFAULT_SHOW_AGE = FALSE;
+$DEFAULT_SHOW_TYPE = TRUE;
+$DEFAULT_SHOW_DESCRIPTION = TRUE;
+$DEFAULT_SHOW_USERS = FALSE;
+$DEFAULT_SHOW_INSTALLS = TRUE;
+$DEFAULT_SHOW_OWNER = FALSE;
+$DEFAULT_SHOW_REPORTER = FALSE;
+
+if (empty($cols)) {
+    $col_uri_part = '';
+
+    $show_dust = $DEFAULT_SHOW_DUST;
+    $show_age = $DEFAULT_SHOW_AGE;
+    $show_type = $DEFAULT_SHOW_TYPE;
+    $show_description = $DEFAULT_SHOW_DESCRIPTION;
+    $show_users = $DEFAULT_SHOW_USERS;
+    $show_installs = $DEFAULT_SHOW_INSTALLS;
+    $show_owner = $DEFAULT_SHOW_OWNER;
+    $show_reporter = $DEFAULT_SHOW_REPORTER;
+} else {
+    if (($show_dust == $DEFAULT_SHOW_DUST)
+            && ($show_age == $DEFAULT_SHOW_AGE)
+            && ($show_type == $DEFAULT_SHOW_TYPE)
+            && ($show_description == $DEFAULT_SHOW_DESCRIPTION)
+            && ($show_users == $DEFAULT_SHOW_USERS)
+            && ($show_installs == $DEFAULT_SHOW_INSTALLS)
+            && ($show_owner == $DEFAULT_SHOW_OWNER)
+            && ($show_reporter == $DEFAULT_SHOW_REPORTER)) {
+        $col_uri_part = '';
+    } else {
+        $col_uri_part = "col%5B%5D=" . implode("&col%5B%5D=", $cols) . "&";
+    }
+}
+
+
+
+// Magic quotes
+// http://de3.php.net/manual/en/security.magicquotes.php#59438
+if (get_magic_quotes_gpc()) {
+    echo "Magic quotes is borking the request data. php.ini missing?";
+    exit(1);
+}
+
+// Page header
+echo "<html>\n";
+echo "<head>\n";
+echo "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n";
+echo "<title>$TITLE</title>\n";
+
+$COLORS = array('#E7FFDF', '#FFEAEA', '#D8F0F8', '#FFD3FF', '#FFFFD7', '#DBDBFF');
+
+echo "<style>\n";
+echo "    TD.ITA { background-color: #FFFFFF; }\n";
+echo "    TD.ITP { background-color: #FFFFFF; }\n";
+echo "    TD.O { background-color: $COLORS[0]; }\n";
+echo "    TD.RFA { background-color: $COLORS[1]; }\n";
+echo "    TD.RFH { background-color: $COLORS[2]; }\n";
+echo "    TD.RFP { background-color: $COLORS[4]; }\n";
+echo "</style>\n";
+
+echo "</head>\n";
+echo "<body style=\"margin:0;\">\n";
+
+echo "<table width=\"100%\" bgcolor=\"#C0C0C0\" cellspacing=\"0\" cellpadding=\"0\">\n";
+echo "<tr>\n";
+echo "    <td align=\"left\">\n";
+echo "        <table cellspacing=\"0\" cellpadding=\"0\">\n";
+echo "        <tr>\n";
+echo "            <td valign=\"center\" style=\"padding:1 2 1 4;\"><img src=\"images/feed-icon.png\" width=\"20\" height=\"20\"></td>\n";
+echo "            <td valign=\"center\" style=\"margin:0;padding:0;\">\n";
+echo "                <form action=\"news.php5\" method=\"GET\" style=\"margin:0;padding:2;\">\n";
+echo "                <select name=\"data\" size=\"1\" style=\"background-color:#C0C0C0;\">\n";
+echo "                    <option value=\"all\">All Changes</option>\n";
+echo "                    <option value=\"good_news\">Good News</option>\n";
+echo "                    <option value=\"bad_news\">Bad News</option>\n";
+echo "                    <option value=\"help_existing\" selected>Help Existing Packages</option>\n";
+echo "                    <option value=\"new_packages\">New Packages</option>\n";
+echo "                </select> <select name=\"title_format\" size=\"1\" style=\"background-color:#C0C0C0;\">\n";
+echo "                    <option value=\"0\" selected>Default Title Format (0)</option>\n";
+echo "                    <option value=\"1\">Alternative Title Format (1)</option>\n";
+echo "                </select> <input type=\"submit\" value=\"Feed\">\n";
+echo "                </form>\n";
+echo "            </td>\n";
+echo "        </tr>\n";
+echo "        </table>\n";
+echo "    </td>\n";
+echo "    <td align=\"right\">\n";
+echo "        <table cellspacing=\"0\" cellpadding=\"0\">\n";
+echo "        <tr>\n";
+echo "            <td valign=\"center\" style=\"padding:1 2 1 2;\"><img src=\"images/valid-rss-20.png\" width=\"57\" height=\"20\"></td>\n";
+echo "            <td valign=\"center\" style=\"margin:0;padding:0;\">\n";
+echo "                <form action=\"http://feedvalidator.org/check.cgi\" method=\"GET\" style=\"margin:0;padding:2;\">\n";
+echo "                <input type=\"hidden\" name=\"url\" value=\"http://debian.binera.de/wnpp/news.php5?data=all&amp;amp;title_format=0\">\n";
+echo "                <input type=\"submit\" value=\"Validate\">\n";
+echo "                </form>\n";
+echo "            </td>\n";
+echo "        </tr>\n";
+echo "        </table>\n";
+echo "    </td>\n";
+echo "</tr>\n";
+echo "<tr>\n";
+echo "    <td bgcolor=\"#000000\" colspan=\"2\" style=\"font-size:1px\">&nbsp;</td>\n";
+echo "</tr>\n";
+echo "</table>\n";
+echo "<br>\n";
+
+
+
+
+
+
+echo "<table width=\"100%\">\n";
+echo "<tr>\n";
+echo "    <td align=\"center\">\n";
+echo "        <h1>$TITLE</h1>\n";
+echo "        <form action=\"\" method=\"get\">\n";
+echo "        <table border=\"1\">\n";
+echo "        <tr>\n";
+echo "            <td>\n";
+echo "                <table>\n";
+echo "                <tr>\n";
+echo "                    <td valign=\"top\">\n";
+echo "                        <select multiple size=\"8\" name=\"type[]\">\n";
+echo "                        <option " . ($show_ita ? "selected " : "") . "value=\"ITA\">ITA&nbsp;</option>\n";
+echo "                        <option " . ($show_itp ? "selected " : "") . "value=\"ITP\">ITP&nbsp;</option>\n";
+echo "                        <option " . ($show_o   ? "selected " : "") . "value=\"O\">O&nbsp;</option>\n";
+echo "                        <option " . ($show_rfa ? "selected " : "") . "value=\"RFA\">RFA&nbsp;</option>\n";
+echo "                        <option " . ($show_rfh ? "selected " : "") . "value=\"RFH\">RFH&nbsp;</option>\n";
+echo "                        <option " . ($show_rfp ? "selected " : "") . "value=\"RFP\">RFP&nbsp;</option>\n";
+echo "                        </select>\n";
+echo "                    </td>\n";
+echo "                    <td valign=\"top\">\n";
+echo "                        <table height=\"100%\">\n";
+echo "                        <tr>\n";
+echo "                            <td>\n";
+echo "                                <table>\n";
+echo "                                <tr>\n";
+echo "                                    <td>Project:</td>\n";
+if (!empty($_GET['project'])) {
+    $project_filter = htmlspecialchars($_GET['project']);
+    $project_uri_part = "project=" . urlencode($_GET['project']) . "&";
+} else {
+    $project_filter = "";
+    $project_uri_part = "";
+}
+echo "                                    <td><input type=\"text\" size=\"30\" name=\"project\" value=\"$project_filter\"></td>\n";
+echo "                                </tr>\n";
+echo "                                <tr>\n";
+echo "                                    <td>Description:</td>\n";
+if (!empty($_GET['description'])) {
+    $description_filter = htmlspecialchars($_GET['description']);
+    $description_uri_part = "description=" . urlencode($_GET['description']) . "&";
+} else {
+    $description_filter = "";
+    $description_uri_part = "";
+}
+echo "                                    <td><input type=\"text\" size=\"30\" name=\"description\" value=\"$description_filter\"></td>\n";
+echo "                                </tr>\n";
+echo "                                <tr>\n";
+echo "                                    <td>Owner:</td>\n";
+echo "                                    <td><input type=\"checkbox\" name=\"owner[]\" value=\"yes\"" . ($with_owner ? "checked " : "") . ">With"
+        . "&nbsp;&nbsp;<input type=\"checkbox\" name=\"owner[]\" value=\"no\"" . ($without_owner ? "checked " : "") . ">Without</td>\n";
+echo "                                </tr>\n";
+echo "                                </table>\n";
+echo "                            </td>\n";
+echo "                        </tr>\n";
+echo "                        <tr>\n";
+echo "                            <td valign=\"bottom\">\n";
+echo "                                <table width=\"100%\">\n";
+echo "                                <tr>\n";
+echo "                                    <td align=\"left\"><a href=\"cron_sync_list.php5\" target=\"_blank\">Force BTS sync</a></td>\n";
+echo "                                    <td align=\"right\"><input type=\"submit\" value=\"Query\"></td>\n";
+echo "                                </tr>\n";
+echo "                                </table>\n";
+echo "                            </td>\n";
+echo "                        </tr>\n";
+echo "                        </table>\n";
+echo "                    </td>\n";
+echo "                    <td valign=\"top\">\n";
+echo "                        <select multiple size=\"8\" name=\"col[]\">\n";
+echo "                        <option " . ($show_dust ? "selected " : "") . "value=\"dust\">Dust</option>\n";
+echo "                        <option " . ($show_age ? "selected " : "") . "value=\"age\">Age</option>\n";
+echo "                        <option " . ($show_type ? "selected " : "") . "value=\"type\">Type</option>\n";
+echo "                        <option " . ($show_description ? "selected " : "") . "value=\"description\">Description</option>\n";
+echo "                        <option " . ($show_users ? "selected " : "") . "value=\"users\">Users</option>\n";
+echo "                        <option " . ($show_installs ? "selected " : "") . "value=\"installs\">Installs</option>\n";
+echo "                        <option " . ($show_owner ? "selected " : "") . "value=\"owner\">Owner</option>\n";
+echo "                        <option " . ($show_reporter ? "selected " : "") . "value=\"reporter\">Reporter</option>\n";
+echo "                        </select>\n";
+echo "                    </td>\n";
+echo "                </tr>\n";
+echo "                </table>\n";
+echo "            </td>\n";
+echo "        </tr>\n";
+echo "        </table>\n";
+if (!empty($_GET['sort'])) {
+echo "        <input type=\"hidden\" name=\"sort\" value=\"" . $_GET['sort'] . "\">\n";
+}
+echo "        </form>\n";
+
+
+
+function make_like_chain($user_col, $words, $empty_value, $op) {
+    if (empty($words)) {
+        return $empty_value;
+    }
+
+    return "($user_col LIKE '%" . implode("%') $op ($user_col LIKE '%", $words) . "%')";
+}
+
+function make_condition($get_var, $user_col) {
+    if (!isset($_GET[$get_var])) {
+        return "1";
+    }
+
+    if ($user_col == "") {
+        $user_col = $get_var;
+    }
+
+    $words = explode(" ", mysql_real_escape_string($_GET[$get_var]));
+    if (empty($words)) {
+        return "1";
+    }
+
+    $positive = array();
+    $negative = array();
+    $matches = array();
+
+    foreach($words as $i) {
+        if (!preg_match("/^([+-]?)(.+)$/", $i, $matches)) {
+            continue;
+        }
+
+        $signum = $matches[1];
+        // Fix for SQL
+        $word = str_replace(array('_', '%'), array('\_','\%'), $matches[2]);
+        if ($signum == "-") {
+            array_push($negative, $word);
+        } else {
+            array_push($positive, $word);
+        }
+    }
+
+    $cond_positive = make_like_chain($user_col, $positive, "1", "AND");
+    $cond_negative = make_like_chain($user_col, $negative, "0", "OR");
+
+    return "(($cond_positive) AND NOT ($cond_negative))";
+}
+
+$project_match = make_condition("project", "project");
+$description_match = make_condition("description", "description");
+
+
+
+// Connect
+$link = mysql_connect($SERVER, $USERNAME, $PASSWORD);
+mysql_select_db($DATABASE);
+
+// Get list
+$condition = "($type_match AND $project_match AND $description_match AND $owner_match)";
+
+// What columns do we need
+$query_cols = array();
+array_push($query_cols, 'GROUP_CONCAT(ident ORDER BY ident ASC SEPARATOR \',\') AS ident_list');
+if ($show_dust) { array_push($query_cols, 'UNIX_TIMESTAMP(' . to_order_col('dust') . ') AS unix_mod_stamp'); }
+if ($show_age) { array_push($query_cols, 'UNIX_TIMESTAMP(' . to_order_col('age') . ') AS unix_open_stamp'); }
+array_push($query_cols, 'type');
+array_push($query_cols, 'project');
+if ($show_description) { array_push($query_cols, to_order_col('description')); }
+if ($show_users) { array_push($query_cols, to_order_col('users')); }
+if ($show_installs) { array_push($query_cols, to_order_col('installs')); }
+if ($show_owner) { array_push($query_cols, to_order_col('owner')); }
+if ($show_reporter) { array_push($query_cols, to_order_col('reporter')); }
+
+$col_part = implode(',', $query_cols);
+$query = "SELECT $col_part "
+        . "FROM $WNPP_TABLE " . (($show_users || $show_installs) ? "LEFT JOIN $POPCON_TABLE ON project = package " : ' ')
+        . "WHERE $condition GROUP BY project ORDER BY ${order_col} ${order_dir}";
+$result = mysql_query($query);
+// echo "[$query]<br>\n"; // XXX
+$count = $result ? mysql_num_rows($result) : 0;
+
+
+
+// Legend
+echo "ITA/ITP = <i>Intent to <u>p</u>ackage/<u>a</u>dopt</i> ..... O = <i><u>O</u>rphaned</i> ..... RFA/RFH/RFP = <i>Request for <u>a</u>doption/<u>h</u>elp/<u>p</u>ackaging</i><br>\n";
+echo "<br>\n";
+
+echo "    </td>\n";
+echo "</tr>\n";
+echo "</table>\n";
+echo "<table width=\"100%\">\n";
+echo "<tr>\n";
+echo "    <td align=\"center\">\n";
+
+// Table header
+// NOTE: Order should match that appearing in the form to give identical URLs where possible
+$uri_part_but_sort = "?" . $type_uri_part . $project_uri_part . $description_uri_part . $owner_uri_part . $col_uri_part;
+echo "<table border=\"1\" cellpadding=\"4\" cellspacing=\"1\">\n";
+echo "<tr>";
+    echo "<th align=\"right\">&nbsp;#&nbsp;</th>";
+    if ($show_dust) {
+        echo "<th>&nbsp;<a href=\"" . $uri_part_but_sort . get_sort_part_for_column('dust') . "\" title=\"Number of days without changes\">Dust</a>&nbsp;</th>";
+    }
+    if ($show_age) {
+        echo "<th>&nbsp;<a href=\"" . $uri_part_but_sort . get_sort_part_for_column('age') . "\" title=\"Number of days since this bug's creation\">Age</a>&nbsp;</th>";
+    }
+    if ($show_type) {
+        echo "<th><a href=\"" . $uri_part_but_sort . get_sort_part_for_column('type') . "\">Type</a></th>";
+    }
+    echo "<th><a href=\"" . $uri_part_but_sort . get_sort_part_for_column('project') . "\">Project</a></th>";
+    if ($show_description) {
+        echo "<th>Description</th>";
+    }
+    if ($show_users) {
+        echo "<th>&nbsp;<a href=\"" . $uri_part_but_sort . get_sort_part_for_column('users') . "\" title=\"Minimum number of people using this package on a regular basis\">Users</a>&nbsp;</th>";
+    }
+    if ($show_installs) {
+        echo "<th>&nbsp;<a href=\"" . $uri_part_but_sort . get_sort_part_for_column('installs') . "\" title=\"Minimum number of people having this package installed\">Installs</a>&nbsp;</th>";
+    }
+    if ($show_owner) {
+        echo "<th><a href=\"" . $uri_part_but_sort . get_sort_part_for_column('owner') . "\">Owner</a></th>";
+    }
+    if ($show_reporter) {
+        echo "<th><a href=\"" . $uri_part_but_sort . get_sort_part_for_column('reporter') . "\">Reporter</a></th>";
+    }
+echo "</tr>\n";
+
+/*
+// http://de3.php.net/manual/en/function.utf8-decode.php#51417
+function is_utf8($string) {
+    return (preg_match('/^(?:[\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}'
+            . '|[\xf0-\xf7][\x80-\xbf]{3}|[\xf8-\xfb][\x80-\xbf]{4}|'
+            . '[\xfc-\xfd][\x80-\xbf]{5})*$/', $string) === 1);
+}
+*/
+
+// http://de3.php.net/manual/en/function.ucwords.php#76786
+function custom_cap($name) {
+    // $name = strtolower($name);
+    $name = mb_strtolower($name, "UTF-8");
+    $name = join("'", array_map('ucwords', explode("'", $name)));
+    $name = join("-", array_map('ucwords', explode("-", $name)));
+    $name = join("Mac", array_map('ucwords', explode("Mac", $name)));
+    $name = join("Mc", array_map('ucwords', explode("Mc", $name)));
+    return $name;
+}
+
+/* TEST CASES
+    Tyler Macdonald
+    Marc-andr Lureau
+    Mario Izquierdo \(mariodebian\)
+    Aurlien Grme
+    Chanop Silpa-anan
+*/
+
+function name_only($mail_and_name) {
+    if (empty($mail_and_name)) {
+        return "<i>nobody</i>";
+    }
+
+    $matches = array();
+    if (!preg_match("/^([^@]+)\s+<[^>]+>$/", $mail_and_name, $matches)) {
+        return "<i>hidden</i>";
+    }
+
+        $text = str_replace("\"", "", $matches[1]);
+        $text = str_replace(array("\\(", "\\)"), array("(", ")"), $text);
+    return htmlspecialchars(custom_cap($text));
+}
+
+function shrink($text, $maxlen) {
+    return (strlen($text) > $maxlen)
+            ? substr($text, 0, $maxlen - 4) . "[..]"
+            : $text;
+}
+
+function null_is_zero($value) {
+    return empty($value) ? 0 : $value;
+}
+
+// Table body, get single entries
+for ($i = 0; $i < $count; $i++) {
+    $entry = mysql_fetch_assoc($result);
+
+    echo "<tr>";
+        $row = $i + 1;
+        $type = $entry['type'];
+        echo "<td class=\"$type\" align=\"right\">&nbsp;$row&nbsp;</td>";
+
+        if ($show_dust) {
+            $dust = (int)((time() - $entry['unix_mod_stamp']) / 60 / 60 / 24);
+            echo "<td class=\"$type\" align=\"right\">&nbsp;$dust&nbsp;</td>";
+        }
+        if ($show_age) {
+            $age = (int)((time() - $entry['unix_open_stamp']) / 60 / 60 / 24);
+            echo "<td class=\"$type\" align=\"right\">&nbsp;$age&nbsp;</td>";
+        }
+        if ($show_type) {
+            echo "<td class=\"$type\"><nobr>$type</nobr></td>";
+        }
+
+        $project = shrink($entry['project'], $MAX_PROJECT_LEN);
+        $ident_list = explode(',', $entry['ident_list']);
+        $count_ident_list = count($ident_list);
+        $url_base = 'http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=';
+        $project_cell = '';
+        if ($count_ident_list == 0) {
+            $project_cell = '<nobr><i>ERROR</i></nobr>';
+        } else if ($count_ident_list == 1) {
+            $project_cell = '<nobr><a href="' . $url_base . $ident_list[0] . '">' . $project . '</a></nobr>';
+        } else {
+            $project_cell = "<nobr>$project ";
+            for ($j = 0; $j < $count_ident_list; $j++) {
+                $project_cell .= ('<a href="' . $url_base . $ident_list[$j] . '">[' . ($j + 1) . ']');
+            }
+            $project_cell .= '</nobr>';
+        }
+        echo "<td class=\"$type\">$project_cell</td>";
+
+        if ($show_description) {
+            $description = shrink($entry['description'], $MAX_DESCR_LEN);
+            echo "<td class=\"$type\"><nobr>$description</nobr></td>";
+        }
+        if ($show_users) {
+            $users = null_is_zero($entry['vote']);
+            echo "<td class=\"$type\" align=\"right\"><nobr>&nbsp;$users&nbsp;</nobr></td>";
+        }
+        if ($show_installs) {
+            $installs = null_is_zero($entry['inst']);
+            echo "<td class=\"$type\" align=\"right\"><nobr>&nbsp;$installs&nbsp;</nobr></td>";
+        }
+        if ($show_owner) {
+            $owner = name_only($entry['charge_person']);
+            echo "<td class=\"$type\"><nobr>$owner</nobr></td>";
+        }
+        if ($show_reporter) {
+            $reporter = name_only($entry['open_person']);
+            echo "<td class=\"$type\"><nobr>$reporter</nobr></td>";
+        }
+    echo "</tr>\n";
+}
+
+// Page footer
+echo "</table>\n";
+echo "    </td>\n";
+echo "</tr>\n";
+echo "</table>\n";
+echo "</body>\n";
+echo "</html>\n";
+
+// Disconnect
+mysql_close($link);
+
+?>


Property changes on: wnpp/index.php5
___________________________________________________________________
Name: svn:executable
   + *

Added: wnpp/news.php5
===================================================================
--- wnpp/news.php5	                        (rev 0)
+++ wnpp/news.php5	2008-01-29 19:32:07 UTC (rev 681)
@@ -0,0 +1,236 @@
+<?php
+/**
+ * Debian WNPP related PHP/MySQL Scripts
+ *
+ * Copyright (C) 2008 Sebastian Pipping
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Sebastian Pipping, webmaster at hartwork.org
+ */
+
+include("config_inc.php5");
+include("cron_shared.php5");
+
+$DEBUG = FALSE;
+
+function open_feed() {
+    global $DEBUG;
+    if ($DEBUG) {
+        header("Content-type: text/plain");
+    } else {
+        header("Content-type: application/rss+xml");
+    }
+
+    echo "<?xml version=\"1.0\"?>\n";
+    echo "<rss version=\"2.0\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n";
+    echo "  <channel>\n";
+    echo "\n";
+}
+
+// Title style
+if (!empty($_GET['title_format'])) {
+    $title_format = $_GET['title_format'];
+} else {
+    $title_format = 0;
+}
+switch ($title_format) {
+case 0:
+case 1:
+    break;
+
+default:
+    $title_format = 0;
+}
+
+// Data set
+if (!empty($_GET['data'])) {
+    $data = $_GET['data'];
+} else {
+    $data = 'all';
+}
+
+switch ($data) {
+case 'new_packages':
+    $CONDITION = "(event = 'CLOSE') AND (type = 'ITP')";
+    $FEED_TITLE = "New Debian Packages";
+    break;
+
+case 'good_news':
+    $CONDITION = "(event = 'CLOSE') OR ((event IN ('MOD','OPEN')) AND (type IN ('ITA','ITP')))";
+    $FEED_TITLE = "Good News on Debian Packages";
+    break;
+
+case 'bad_news':
+    $CONDITION = "!((event = 'CLOSE') OR ((event IN ('MOD','OPEN')) AND (type IN ('ITA','ITP'))))";
+    $FEED_TITLE = "Bad News on Debian Packages";
+    break;
+
+case 'help_existing':
+    $CONDITION = "(event IN ('OPEN','MOD')) AND (type IN ('O','RFA','RFH'))";
+    $FEED_TITLE = "Existing Debian Packages In Need For Help";
+    break;
+
+case 'all': // fall through
+default:
+    $data = 'all';
+    $CONDITION = "1";
+    $FEED_TITLE = "Debian Packaging News";
+    break;
+}
+
+$DATA_QUERY = "SELECT ident,type,before_type,after_type,project,description,event,UNIX_TIMESTAMP(event_stamp) AS unix_event_stamp "
+        . "FROM $LOG_INDEX_TABLE LEFT JOIN $LOG_MODS_TABLE ON $LOG_INDEX_TABLE.log_id = $LOG_MODS_TABLE.log_id "
+        . "WHERE $CONDITION ORDER BY event_stamp DESC LIMIT 30";
+$MAX_QUERY = "SELECT UNIX_TIMESTAMP(MAX(event_stamp)) AS unix_event_stamp FROM $LOG_INDEX_TABLE WHERE $CONDITION";
+
+function print_feed_header($unix_content_change) {
+    global $data;
+    global $title_format;
+    global $DEBUG;
+    global $FEED_TITLE;
+    $lastBuildDate = date('r', $unix_content_change);
+    $self_url = "http://debian.binera.de/wnpp/news.php5?data=$data&amp;amp;title_format=$title_format";
+
+    if (!$DEBUG) {
+        echo "    <title>$FEED_TITLE</title>\n";
+    }
+    echo "    <link>$self_url</link>\n";
+    echo "    <atom:link href=\"$self_url\" rel=\"self\" type=\"application/rss+xml\" />\n";
+    echo "    <description>Debian news feed on packaging bugs</description>\n";
+    echo "    <language>en-us</language>\n";
+    echo "    <pubDate>$lastBuildDate</pubDate>\n";
+    echo "    <lastBuildDate>$lastBuildDate</lastBuildDate>\n";
+    echo "    <webMaster>webmaster at hartwork.org (Sebastian Pipping)</webMaster>\n";
+    echo "    <ttl>15</ttl>\n"; // because the cron runs every 30 minutes
+    echo "\n";
+}
+
+function close_feed() {
+    echo "\n";
+    echo "  </channel>\n";
+    echo "</rss>\n";
+}
+
+function cleanup() {
+    global $link;
+
+    // Disconnect
+    mysql_close($link);
+
+    close_feed();
+}
+
+open_feed();
+
+// Connect to database
+$link = mysql_connect($SERVER, $USERNAME, $PASSWORD);
+mysql_select_db($DATABASE);
+
+function escape_xml($text) {
+    // Extensible Markup Language (XML) 1.0 (Fourth Edition)
+    // 2.4 Character Data and Markup
+    // http://www.w3.org/TR/REC-xml/#syntax
+    return str_replace(array('&', '<', '>', '\'', '"'),
+            array('&amp;', '&lt;', '&gt;', '&apos;', '&quot;'),
+            $text);
+}
+
+function print_entry($entry) {
+    global $title_format;
+
+    $type = $entry['type'];
+    $after_type = $entry['after_type'];
+    $before_type = $entry['before_type'];
+    $ident = $entry['ident'];
+    $project = $entry['project'];
+    $description = $entry['description'];
+    $event = $entry['event'];
+    $rfc822 = date("r", $entry['unix_event_stamp']);
+
+    switch($event) {
+    case 'CLOSE':
+        $type_title_part = $type;
+        $event_title_part = "Closed";
+        break;
+
+    case 'MOD': // fall through
+        $type_title_part = "$before_type -> $after_type";
+        $event_title_part = "Modified";
+        break;
+
+    case 'OPEN': // fall through
+    default:
+        $type_title_part = $type;
+        $event_title_part = "Opened";
+        break;
+    }
+
+    switch ($title_format) {
+    case 1:
+        if ($event != 'CLOSE') {
+            $title = '#' . "$ident $type_title_part: $project -- $description";
+        } else {
+            $title = "CLOSED : $project -- $description";
+        }
+        break;
+
+    case 0: // fall through
+    default:
+        $title = "$event_title_part [$type_title_part] $project -- $description";
+    }
+    $title = escape_xml($title);
+
+    $url = 'http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=' . $ident;
+    $author = $ident . '@bugs.debian.org';
+
+    echo "    <item>\n";
+    echo "      <title>$title</title>\n";
+    echo "      <link>$url</link>\n";
+    echo "      <description>$url</description>\n";
+    echo "      <pubDate>$rfc822</pubDate>\n";
+    echo "      <guid>$url</guid>\n";
+    echo "      <dc:creator>$author</dc:creator>\n";
+    echo "    </item>\n";
+}
+
+// Feed header
+$query = $MAX_QUERY;
+$result = mysql_query($query);
+if (!$result) {
+    cleanup();
+    exit(0);
+}
+$entry = mysql_fetch_assoc($result);
+$unix_content_change = $entry['unix_event_stamp'];
+print_feed_header($unix_content_change);
+
+// Feed data
+$query = $DATA_QUERY;
+// echo "[$query]\n";
+$result = mysql_query($query);
+if (!$result) {
+    cleanup();
+    exit(0);
+}
+$count = mysql_num_rows($result);
+for ($i = 0; $i < $count; $i++) {
+    $entry = mysql_fetch_assoc($result);
+    print_entry($entry);
+}
+
+cleanup();
+
+?>

Added: wnpp/php.ini
===================================================================
--- wnpp/php.ini	                        (rev 0)
+++ wnpp/php.ini	2008-01-29 19:32:07 UTC (rev 681)
@@ -0,0 +1,3 @@
+magic_quotes_runtime=off
+magic_quotes_gpc=off
+magic_quotes_sybase=off

Added: wnpp/soap_test.php5
===================================================================
--- wnpp/soap_test.php5	                        (rev 0)
+++ wnpp/soap_test.php5	2008-01-29 19:32:07 UTC (rev 681)
@@ -0,0 +1,13 @@
+<?php
+header("Content-type: text/plain;charset=utf-8");
+
+$bugnumber = 433106;
+$client = new SoapClient(NULL,
+        array('location' => "http://bugs.debian.org/cgi-bin/soap.cgi",
+        'uri' => "Debbugs/SOAP",
+        'proxy_host' => "http://bugs.debian.org"));
+$response = $client->__soapCall("get_status", array('bug'=>$bugnumber));
+$obj = $response[$bugnumber];
+
+print_r($obj);
+?>
\ No newline at end of file

Added: wnpp/tables/table_structures.sql
===================================================================
--- wnpp/tables/table_structures.sql	                        (rev 0)
+++ wnpp/tables/table_structures.sql	2008-01-29 19:32:07 UTC (rev 681)
@@ -0,0 +1,94 @@
+-- 
+-- Debian WNPP related PHP/MySQL Scripts
+-- 
+-- Copyright (C) 2008 Sebastian Pipping
+-- 
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 2 of the License, or
+-- (at your option) any later version.
+-- 
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+-- 
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-- 
+-- Sebastian Pipping, webmaster at hartwork.org
+
+-- phpMyAdmin SQL Dump
+-- version 2.10.1
+-- http://www.phpmyadmin.net
+
+SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
+
+-- 
+-- Table structure for table `debian_log_index`
+-- 
+
+DROP TABLE IF EXISTS `debian_log_index`;
+CREATE TABLE `debian_log_index` (
+  `log_id` int(11) NOT NULL auto_increment,
+  `ident` int(11) default NULL,
+  `type` enum('ITA','ITP','O','RFA','RFH','RFP') default 'RFH',
+  `project` varchar(255) default NULL,
+  `description` varchar(255) default NULL,
+  `log_stamp` timestamp NULL default CURRENT_TIMESTAMP,
+  `event` enum('OPEN','MOD','CLOSE') NOT NULL default 'MOD',
+  `event_stamp` timestamp NULL default NULL,
+  PRIMARY KEY  (`log_id`)
+) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=92 ;
+
+-- --------------------------------------------------------
+
+-- 
+-- Table structure for table `debian_log_mods`
+-- 
+
+DROP TABLE IF EXISTS `debian_log_mods`;
+CREATE TABLE `debian_log_mods` (
+  `log_id` int(11) NOT NULL default '0',
+  `before_type` enum('ITA','ITP','O','RFA','RFH','RFP') default NULL,
+  `after_type` enum('ITA','ITP','O','RFA','RFH','RFP') default NULL,
+  PRIMARY KEY  (`log_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
+-- 
+-- Table structure for table `debian_popcon`
+-- 
+
+DROP TABLE IF EXISTS `debian_popcon`;
+CREATE TABLE `debian_popcon` (
+  `package` varchar(255) NOT NULL default '',
+  `inst` int(11) default NULL,
+  `vote` int(11) default NULL,
+  `old` int(11) default NULL,
+  `recent` int(11) default NULL,
+  `nofiles` int(11) default NULL,
+  PRIMARY KEY  (`package`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
+-- 
+-- Table structure for table `debian_wnpp`
+-- 
+
+DROP TABLE IF EXISTS `debian_wnpp`;
+CREATE TABLE `debian_wnpp` (
+  `ident` int(11) NOT NULL default '0',
+  `open_person` varchar(255) default NULL,
+  `open_stamp` timestamp NULL default NULL,
+  `mod_stamp` timestamp NULL default NULL,
+  `type` enum('ITA','ITP','O','RFA','RFH','RFP') NOT NULL default 'RFH',
+  `project` varchar(255) default NULL,
+  `description` varchar(255) default NULL,
+  `charge_person` varchar(255) default NULL,
+  `cron_stamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
+  PRIMARY KEY  (`ident`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;




More information about the Collab-qa-commits mailing list