From 8f28ae10c40de0794a72fef07f7e05f1017cb691 Mon Sep 17 00:00:00 2001 From: Jeremy Newman Date: Mon, 15 Mar 2004 16:22:00 +0000 Subject: [PATCH] Initial revision --- README | 5 + account.php | 197 ++++++++++ addcomment.php | 98 +++++ admin/.cvsignore | 2 + admin/addAppFamily.php | 37 ++ admin/addAppNote.php | 51 +++ admin/addAppVersion.php | 48 +++ admin/addCategory.php | 42 +++ admin/addVendor.php | 44 +++ admin/adminAppQueue.php | 308 ++++++++++++++++ admin/deleteAny.php | 99 +++++ admin/editAppFamily.php | 93 +++++ admin/editAppNote.php | 46 +++ admin/editAppOwners.php | 120 ++++++ admin/editAppVersion.php | 111 ++++++ admin/editBundle.php | 98 +++++ admin/editCategory.php | 42 +++ admin/editVendor.php | 41 +++ admin/index.php | 78 ++++ admin/path.php | 3 + apidb.css | 160 ++++++++ appbrowse.php | 140 +++++++ appimage.php | 96 +++++ appsubmit.php | 85 +++++ appview.php | 420 +++++++++++++++++++++ banner/468x60/cw-ad01.gif | Bin 0 -> 13337 bytes banner/468x60/cw-ad02.gif | Bin 0 -> 11594 bytes banner/468x60/cw-ad04.gif | Bin 0 -> 18875 bytes banner/xml/cw-ad01.xml | 7 + banner/xml/cw-ad02.xml | 7 + banner/xml/cw-ad04.xml | 7 + commentview.php | 21 ++ edituser.php | 55 +++ favicon.ico | Bin 0 -> 3638 bytes help/.cvsignore | 2 + help/appdb_faq.help | 66 ++++ help/generic.help | 54 +++ help/index.php | 102 ++++++ help/path.php | 3 + help/privacy.help | 45 +++ help/ratings.help | 95 +++++ help/voting.help | 40 ++ images/appdb_montage.jpg | Bin 0 -> 24224 bytes images/back.gif | Bin 0 -> 128 bytes images/bk.gif | Bin 0 -> 109 bytes images/blank.gif | Bin 0 -> 61 bytes images/compare.gif | Bin 0 -> 146 bytes images/go.gif | Bin 0 -> 130 bytes images/grey_pixel.gif | Bin 0 -> 43 bytes images/list.gif | Bin 0 -> 114 bytes images/next.gif | Bin 0 -> 126 bytes images/no_screenshot.gif | Bin 0 -> 903 bytes images/remove.gif | Bin 0 -> 144 bytes images/s0.gif | Bin 0 -> 59 bytes images/s1.gif | Bin 0 -> 117 bytes images/s2.gif | Bin 0 -> 117 bytes images/tree.gif | Bin 0 -> 116 bytes images/w0.gif | Bin 0 -> 65 bytes images/w1.gif | Bin 0 -> 297 bytes images/winehq_border_bottom_left.gif | Bin 0 -> 125 bytes images/winehq_border_bottom_right.gif | Bin 0 -> 105 bytes images/winehq_border_dot_left.gif | Bin 0 -> 114 bytes images/winehq_border_dot_right.gif | Bin 0 -> 114 bytes images/winehq_border_top_left.gif | Bin 0 -> 125 bytes images/winehq_border_top_right.gif | Bin 0 -> 105 bytes images/winehq_top_logo.gif | Bin 0 -> 9380 bytes include/.cvsignore | 2 + include/appbyvendor_inc.php | 58 +++ include/appdb.php | 35 ++ include/application.php | 78 ++++ include/appversion_inc.php | 61 ++++ include/banner.php | 55 +++ include/category.php | 208 +++++++++++ include/comments.php | 251 +++++++++++++ include/config.php | 27 ++ include/db.php | 35 ++ include/footer.php | 8 + include/form_edit.php | 41 +++ include/form_login.php | 61 ++++ include/form_new.php | 53 +++ include/header.php | 51 +++ include/html.php | 351 ++++++++++++++++++ include/incl.php | 241 ++++++++++++ include/menu.php | 77 ++++ include/parsedate.php | 81 +++++ include/pn_buttons.php | 76 ++++ include/qclass.php | 246 +++++++++++++ include/query_appbyvendor.php | 37 ++ include/query_apps.php | 53 +++ include/query_inc.php | 189 ++++++++++ include/query_users.php | 59 +++ include/query_vendors.php | 37 ++ include/rating.php | 210 +++++++++++ include/session.php | 113 ++++++ include/sidebar.php | 41 +++ include/sidebar_admin.php | 26 ++ include/sidebar_login.php | 28 ++ include/tableve.php | 503 ++++++++++++++++++++++++++ include/user.php | 319 ++++++++++++++++ include/util.php | 174 +++++++++ include/vote.php | 199 ++++++++++ index.php | 70 ++++ noteview.php | 60 +++ path.php | 3 + preferences.php | 106 ++++++ screenshots.php | 103 ++++++ scripts.js | 18 + search.php | 66 ++++ stdquery.php | 125 +++++++ support.php | 42 +++ tables/.htaccess | 2 + tables/appdb_tables.sql | 246 +++++++++++++ tables/appratings.sql | 7 + tables/banner.sql | 12 + tables/prefs_list.sql | 19 + tables/user_list.sql | 19 + tables/user_prefs.sql | 7 + tables/user_privs.sql | 6 + updaterating.php | 18 + updatevote.php | 15 + vendorview.php | 75 ++++ votestats.php | 45 +++ 122 files changed, 8116 insertions(+) create mode 100644 README create mode 100644 account.php create mode 100644 addcomment.php create mode 100644 admin/.cvsignore create mode 100644 admin/addAppFamily.php create mode 100644 admin/addAppNote.php create mode 100644 admin/addAppVersion.php create mode 100644 admin/addCategory.php create mode 100644 admin/addVendor.php create mode 100644 admin/adminAppQueue.php create mode 100644 admin/deleteAny.php create mode 100644 admin/editAppFamily.php create mode 100644 admin/editAppNote.php create mode 100644 admin/editAppOwners.php create mode 100644 admin/editAppVersion.php create mode 100644 admin/editBundle.php create mode 100644 admin/editCategory.php create mode 100644 admin/editVendor.php create mode 100644 admin/index.php create mode 100644 admin/path.php create mode 100644 apidb.css create mode 100644 appbrowse.php create mode 100644 appimage.php create mode 100644 appsubmit.php create mode 100644 appview.php create mode 100644 banner/468x60/cw-ad01.gif create mode 100644 banner/468x60/cw-ad02.gif create mode 100644 banner/468x60/cw-ad04.gif create mode 100644 banner/xml/cw-ad01.xml create mode 100644 banner/xml/cw-ad02.xml create mode 100644 banner/xml/cw-ad04.xml create mode 100644 commentview.php create mode 100644 edituser.php create mode 100644 favicon.ico create mode 100644 help/.cvsignore create mode 100644 help/appdb_faq.help create mode 100644 help/generic.help create mode 100644 help/index.php create mode 100644 help/path.php create mode 100644 help/privacy.help create mode 100644 help/ratings.help create mode 100644 help/voting.help create mode 100644 images/appdb_montage.jpg create mode 100644 images/back.gif create mode 100644 images/bk.gif create mode 100644 images/blank.gif create mode 100644 images/compare.gif create mode 100644 images/go.gif create mode 100644 images/grey_pixel.gif create mode 100644 images/list.gif create mode 100644 images/next.gif create mode 100644 images/no_screenshot.gif create mode 100644 images/remove.gif create mode 100644 images/s0.gif create mode 100644 images/s1.gif create mode 100644 images/s2.gif create mode 100644 images/tree.gif create mode 100644 images/w0.gif create mode 100644 images/w1.gif create mode 100644 images/winehq_border_bottom_left.gif create mode 100644 images/winehq_border_bottom_right.gif create mode 100644 images/winehq_border_dot_left.gif create mode 100644 images/winehq_border_dot_right.gif create mode 100644 images/winehq_border_top_left.gif create mode 100644 images/winehq_border_top_right.gif create mode 100644 images/winehq_top_logo.gif create mode 100644 include/.cvsignore create mode 100644 include/appbyvendor_inc.php create mode 100644 include/appdb.php create mode 100644 include/application.php create mode 100644 include/appversion_inc.php create mode 100644 include/banner.php create mode 100644 include/category.php create mode 100644 include/comments.php create mode 100644 include/config.php create mode 100644 include/db.php create mode 100644 include/footer.php create mode 100644 include/form_edit.php create mode 100644 include/form_login.php create mode 100644 include/form_new.php create mode 100644 include/header.php create mode 100644 include/html.php create mode 100644 include/incl.php create mode 100644 include/menu.php create mode 100644 include/parsedate.php create mode 100644 include/pn_buttons.php create mode 100644 include/qclass.php create mode 100644 include/query_appbyvendor.php create mode 100644 include/query_apps.php create mode 100644 include/query_inc.php create mode 100644 include/query_users.php create mode 100644 include/query_vendors.php create mode 100644 include/rating.php create mode 100644 include/session.php create mode 100644 include/sidebar.php create mode 100644 include/sidebar_admin.php create mode 100644 include/sidebar_login.php create mode 100644 include/tableve.php create mode 100644 include/user.php create mode 100644 include/util.php create mode 100644 include/vote.php create mode 100644 index.php create mode 100644 noteview.php create mode 100644 path.php create mode 100644 preferences.php create mode 100644 screenshots.php create mode 100644 scripts.js create mode 100644 search.php create mode 100644 stdquery.php create mode 100644 support.php create mode 100644 tables/.htaccess create mode 100644 tables/appdb_tables.sql create mode 100644 tables/appratings.sql create mode 100644 tables/banner.sql create mode 100644 tables/prefs_list.sql create mode 100644 tables/user_list.sql create mode 100644 tables/user_prefs.sql create mode 100644 tables/user_privs.sql create mode 100644 updaterating.php create mode 100644 updatevote.php create mode 100644 vendorview.php create mode 100644 votestats.php diff --git a/README b/README new file mode 100644 index 0000000..ddd178a --- /dev/null +++ b/README @@ -0,0 +1,5 @@ +WineHQ Application Database +------------------------------------------------------------------------ +Authors: + Jeremy Newman + Charles Leop diff --git a/account.php b/account.php new file mode 100644 index 0000000..4f46342 --- /dev/null +++ b/account.php @@ -0,0 +1,197 @@ +exists($ext_username)) + { + $ext_username = ""; + retry("new", "That username is already in use"); + return; + } + + $result = $user->create($ext_username, $ext_password, $ext_realname, $ext_email); + + if($result == null) + { + $user->login($ext_username, $ext_password); + addmsg("Account created! ($ext_username)", "green"); + redirect(apidb_fullurl()); + } + else + retry("new", "Failed to create account: $result"); +} + +//email lost password +function cmd_send_passwd() +{ + global $ext_username; + + $user = new User(); + + $userid = $user->lookup_userid($ext_username); + $passwd = generate_passwd(); + + if ($userid) + { + if ($user->update($userid, $passwd)) + { + + $msg = "Application DB Lost Password\n"; + $msg .= "----------------------------\n"; + $msg .= "We have received a request that you lost your password.\n"; + $msg .= "We will create a new password for you. You can then change\n"; + $msg .= "your password at the Preferences screen.\n\n"; + $msg .= "Your new password is: ".$passwd."\n\n"; + + if (mail($user->lookup_email($userid), '[AppDB] Lost Password', $msg)) + { + addmsg("Your new password has been emailed to you.", "green"); + } + else + { + addmsg("Your password has changed, but we could not email it to you. Contact Support!", "red"); + } + } + else + { + addmsg("Internal Error, we could not update your password.", "red"); + } + } + else + { + addmsg("Sorry, that username [$ext_username] does not exist.", "red"); + } + + redirect(apidb_fullurl("account.php?cmd=login")); +} + +//on login handler +function cmd_do_login() +{ + global $ext_username, $ext_password; + global $ext_referer; + global $current; + + $user = new User(); + $result = $user->login($ext_username, $ext_password); + + if($result == null) + { + $current = $user; + addmsg("You are successfully logged in.", "green"); + redirect(apidb_fullurl("index.php")); + } + else + { + retry("login","Login failed ($result)"); + $current = 0; + } +} + +?> diff --git a/addcomment.php b/addcomment.php new file mode 100644 index 0000000..1a95b44 --- /dev/null +++ b/addcomment.php @@ -0,0 +1,98 @@ +userid : 0; + + $result = mysql_query("INSERT INTO appComments VALUES (null, null, $thread, ". + "$appId, $versionId, $userId, '$hostname', '$subject', ". + "'$body', 0)"); + + if (!$result) + { + errorpage('Internal Database Access Error',mysql_error()); + exit; + } + + addmsg("New Comment Posted", "green"); + redirect(apidb_fullurl("appview.php?appId=$appId&versionId=$versionId")); + +} +else +{ + + apidb_header("Add Comment"); + + $mesTitle = "Post New Comment"; + + if($thread) + { + $result = mysql_query("SELECT subject,body FROM appComments WHERE commentId = $thread"); + $ob = mysql_fetch_object($result); + if($ob) + { + $mesTitle = "Replying To ... $ob->subject\n"; + echo html_frame_start($ob->subject,500); + echo htmlify_urls($ob->body), "

\n"; + echo html_frame_end(); + } + } + + echo "
\n"; + + echo html_frame_start($mesTitle,500,"",0); + + echo '',"\n"; + echo "\n"; + echo " \n"; + echo "\n"; + echo " \n"; + echo "\n"; + echo "\n"; + echo "
From:  ". ($current->username ? $current->username : "Anonymous") ."
Subject:  
\n"; + echo " \n"; + echo " \n"; + echo "
\n"; + + echo html_frame_end(); + + echo "\n"; + echo "\n"; + echo "\n"; + echo "

 

\n"; + + apidb_footer(); + +} + +?> diff --git a/admin/.cvsignore b/admin/.cvsignore new file mode 100644 index 0000000..55d2fba --- /dev/null +++ b/admin/.cvsignore @@ -0,0 +1,2 @@ +stderr + diff --git a/admin/addAppFamily.php b/admin/addAppFamily.php new file mode 100644 index 0000000..8d88956 --- /dev/null +++ b/admin/addAppFamily.php @@ -0,0 +1,37 @@ +update($HTTP_POST_VARS); +} +else +{ + $table = "appFamily"; + $query = "INSERT INTO $table VALUES(0, 'NONAME', 0, null, null, null, $catId)"; + + mysql_query("DELETE FROM $table WHERE appName = 'NONAME'"); + + if(debugging()) { echo "

query: $query

"; } + + $t->create($query, $table, "appId"); +} + +apidb_footer(); + +?> diff --git a/admin/addAppNote.php b/admin/addAppNote.php new file mode 100644 index 0000000..d6103a5 --- /dev/null +++ b/admin/addAppNote.php @@ -0,0 +1,51 @@ +ownsApp($appId)) ) +{ + errorpage("Insufficient Privileges!"); + exit; +} + +apidb_header("Add Application Note"); + +$t = new TableVE("create"); + +if($HTTP_POST_VARS) +{ + $t->update($HTTP_POST_VARS); +} +else +{ + $table = "appNotes"; + + if (!$versionId) { $versionId = 0; } + + //delete old NONAMES + mysql_query("DELETE FROM $table WHERE noteTitle = 'NONAME'"); + + //show edit form + $query = "INSERT INTO $table VALUES(0, 'NONAME', '', $appId, $versionId)"; + + if(debugging()) { echo "

query: $query

"; } + + $t->create($query, $table, "noteId"); + + echo html_back_link(1,$apidb_root."appview.php?appId=$appId&versionId=$versionId"); +} + +apidb_footer(); + +?> diff --git a/admin/addAppVersion.php b/admin/addAppVersion.php new file mode 100644 index 0000000..aa9cf3a --- /dev/null +++ b/admin/addAppVersion.php @@ -0,0 +1,48 @@ +update($HTTP_POST_VARS); +} +else +{ + $table = "appVersion"; + $query = "INSERT INTO $table VALUES(0, $appId, 'NONAME', null, null, null, 0.0, 0.0)"; + + mysql_query("DELETE FROM $table WHERE versionName = 'NONAME'"); + + if(debugging()) + echo "$query

\n"; + + $t->create($query, $table, "versionId"); +} + +echo html_back_link(1,$apidb_root."appview.php?appId=$appId"); + +apidb_footer(); + +?> diff --git a/admin/addCategory.php b/admin/addCategory.php new file mode 100644 index 0000000..6cb3625 --- /dev/null +++ b/admin/addCategory.php @@ -0,0 +1,42 @@ +update($HTTP_POST_VARS); +} +else +{ + $table = "appCategory"; + $query = "INSERT INTO $table VALUES(0, 'NONAME', null, 0)"; + + mysql_query("DELETE FROM $table WHERE catName = 'NONAME'"); + + if(debugging()) + echo "$query

\n"; + + $t->create($query, $table, "catId"); +} + +apidb_footer(); + +?> diff --git a/admin/addVendor.php b/admin/addVendor.php new file mode 100644 index 0000000..611067a --- /dev/null +++ b/admin/addVendor.php @@ -0,0 +1,44 @@ +update($HTTP_POST_VARS); +} +else +{ + $table = "vendor"; + $query = "INSERT INTO $table VALUES(0, 'NONAME', null)"; + + mysql_query("DELETE FROM $table WHERE vendorName = 'NONAME'"); + + if(debugging()) + echo "$query

\n"; + + $t->create($query, $table, "vendorId"); +} + +apidb_footer(); + +?> diff --git a/admin/adminAppQueue.php b/admin/adminAppQueue.php new file mode 100644 index 0000000..bdefe4d --- /dev/null +++ b/admin/adminAppQueue.php @@ -0,0 +1,308 @@ +',"\n"; + +if ($sub) +{ + if ($queueId) + { + //get data + $query = "SELECT * from appQueue where queueId = $queueId;"; + $result = mysql_query($query); + $ob = mysql_fetch_object($result); + mysql_free_result($result); + } + else + { + //error no Id! + echo html_frame_start("Error","300"); + echo '

Application Not Found!

',"\n"; + echo html_frame_end(" "); + } + + //process according to sub flag + if ($sub == 'view' && $queueId) + { + $x = new TableVE("view"); + + //help + echo "
\n\n"; + echo "

This is the full view of the application waiting to be approved. You need to pick a category before submitting \n"; + echo "it into the database. If you approve this application, an email will be sent to the author of the submission.

\n"; + echo "

There are two kinds of applications in this database:

\n"; + echo "
    \n"; + echo "
  1. App Family This is a parent group application, that will have multiple versions under it.
    \n"; + echo " To add this submission as a Family, choose 'Application' from the type drop down. Then set the category.\n"; + echo " The version and app parent fields will be ignored in this type.
    \n"; + echo " If the vendor does not exist, leave the vendor drop down unset, and the field will be used.
  2. \n"; + echo "

  3. App Version This type of application will be nested under the selected application parent. The category,\n"; + echo " name, and vendor fields will be ignored.
  4. \n"; + echo "
\n\n"; + + //view application details + echo html_frame_start("New Application Form",400,"",0); + echo "\n"; + + //type + echo '',"\n"; + + //category + echo '',"\n"; + + //app parent + echo '',"\n"; + + //name + echo '',"\n"; + + //version + echo '',"\n"; + + //vendor + echo '',"\n"; + + //alt vendor + echo '',"\n"; + + //url + echo '',"\n"; + + //desc + echo '',"\n"; + + //echo '',"\n"; + //echo '',"\n"; + + echo '',"\n"; + echo '
Type',"\n"; + echo '',"\n"; + echo '
Category',"\n"; + $x->make_option_list("cat","","appCategory","catId","catName"); + echo '
App Parent',"\n"; + $x->make_option_list("appParent","","appFamily","appId","appName"); + echo '
App Name
App Version
App Vendor
 ',"\n"; + $x->make_option_list("altvendor","","vendor","vendorId","vendorName"); + echo '
App URL
App Desc
Email
Image
',"\n"; + echo '',"\n"; + echo '',"\n"; + + echo html_frame_end(" "); + echo html_back_link(1,'adminAppQueue.php'); + } + else if ($sub == 'add' && $queueId) + { + //add item to main db + $statusMessage = ""; + $goodtogo = 0; + if ($type == 'app') + { + //process as application family + if ($altvendor == 0 && $queueVendor) + { + //add new vendor + mysql_query("INSERT into vendor VALUES (null, '".addslashes($queueVendor)."', '');"); + $altvendor = mysql_insert_id(); + } + + $query = "INSERT into appFamily VALUES (null, '". + addslashes($queueName)."', $altvendor, '', '". + addslashes($queueDesc)."', '". + addslashes($queueURL)."', $cat);"; + + if (mysql_query($query)) + { + //get the id of the app just added + $appParent = mysql_insert_id(); + + //delete queue item + mysql_query("DELETE from appQueue where queueId = $queueId;"); + + //set ver if not set + if (!$queueVersion) + $queueVersion = '1.0'; + if (!$queueDesc) + $queueDesc = 'released version'; + + $verQuery = "INSERT into appVersion VALUES (null, $appParent, '". + addslashes($queueVersion)."', '', '". + addslashes($queueDesc)."', '". + addslashes($queueURL)."', 0.0, 0.0);"; + + //Now add a version + if (mysql_query($verQuery)) + { + //successful + $statusMessage = "

The application $queueName was successfully added into the database

\n"; + $goodtogo = 1; + } + else + { + //error + $statusMessage = "

Database Error!
".mysql_error()."

\n"; + $statusMessage .= "

Note: The application family was successfully added.

\n"; + } + + } + else + { + //error + $statusMessage = "

Database Error!
".mysql_error()."

\n"; + } + } + else if ($type == 'ver') + { + //process as application version + if ($appParent) + { + $query = "INSERT into appVersion VALUES (null, $appParent, '". + addslashes($queueVersion)."', '', '". + addslashes($queueDesc)."', '". + addslashes($queueURL)."', 0.0, 0.0);"; + + if (mysql_query($query)) + { + //successful + $statusMessage = "

The application $queueName was successfully added into the database

\n"; + mysql_query("DELETE from appQueue where queueId = $queueId;"); + $goodtogo = 1; + + } + else + { + //error + $statusMessage = "

Database Error!
".mysql_error()."

\n"; + } + } + else + { + $statusMessage = "

Error
You did not pick an application Parent!

\n"; + } + + } + + //Send Status Email + if ($ob->queueEmail && $goodtogo) + { + $ms = "Application Database Status Report\n"; + $ms .= "----------------------------------\n\n"; + $ms .= "Your application ".stripslashes($ob->queueName)." has been entered "; + $ms .= "into the application database.\n\n"; + $ms .= "Thanks!\n"; + + mail(stripslashes($ob->queueEmail),'[AppDB] Status Report',$ms); + } + + //done + echo html_frame_start("Submit Application","300"); + echo "

$statusMessage

\n"; + echo html_frame_end(" "); + echo html_back_link(1,'adminAppQueue.php'); + } + else if ($sub == 'delete' && $queueId) + { + //delete main item + $query = "DELETE from appQueue where queueId = $queueId;"; + $result = mysql_query($query); + echo html_frame_start("Delete Application: $ob->queueName",400,"",0); + if(!$result) + { + //error + echo "

Internal Error: unable to delete selected application!

\n"; + } + else + { + //success + echo "

Application was successfully deleted from the Queue.

\n"; + } + echo html_frame_end(" "); + echo html_back_link(1,'adminAppQueue.php'); + } + else + { + //error no sub! + echo html_frame_start("Error","300"); + echo '

Internal Routine Not Found!

',"\n"; + echo html_frame_end(" "); + echo html_back_link(1,'adminAppQueue.php'); + } +} +else +{ + //get available apps + $query = "SELECT * from appQueue;"; + $result = mysql_query($query); + + if(!$result || !mysql_num_rows($result)) + { + //no apps in queue + echo html_frame_start("","90%"); + echo '

The Application Queue is empty.

',"\n"; + echo '

There is nothing for you to do. Check back later.

',"\n"; + echo html_frame_end(" "); + } + else + { + //help + echo "
\n\n"; + echo "

This is the list of applications waiting for your approval, or to be annihilated from existence.

\n"; + echo "

To view a submission, click on its name. From that page you can edit, and approve it into the AppDB.
\n"; + echo "Click the delete link to remove the selected item from the queue. An email will automatically be sent to the\n"; + echo "submitter to let them know the item was deleted.

\n"; + echo "
\n\n"; + + //show applist + echo html_frame_start("","90%","",0); + echo "\n\n"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c = 1; + while($ob = mysql_fetch_object($result)) + { + if ($c % 2 == 1) { $bgcolor = 'color0'; } else { $bgcolor = 'color1'; } + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + $c++; + } + echo "
Application NameVersionVendorSubmitter Email 
$ob->queueName".stripslashes($ob->queueVersion)."  ".stripslashes($ob->queueVendor)."  ".stripslashes($ob->queueEmail)."  [delete]
\n\n"; + echo html_frame_end(" "); + } + +} + +echo ""; +apidb_footer(); + + +?> diff --git a/admin/deleteAny.php b/admin/deleteAny.php new file mode 100644 index 0000000..8230dcd --- /dev/null +++ b/admin/deleteAny.php @@ -0,0 +1,99 @@ +appId); + $r = mysql_query("DELETE FROM appCategory WHERE catId = $catId"); + + if($r) + addmsg("Category $catId deleted", "green"); + else + addmsg("Failed to delete category $catId:".mysql_error(), "red"); + } + else + { + addmsg("Failed to delete category $catId: ".mysql_error(), "red"); + } +} + +function deleteAppFamily($appId) +{ + $r = mysql_query("DELETE FROM appFamily WHERE appId = $appId"); + if($r) + { + $r = mysql_query("DELETE FROM appVersion WHERE appId = $appId"); + if($r) + addmsg("Application and versions deleted", "green"); + else + addmsg("Failed to delete appVersions: " . mysql_error(), "red"); + } + else + addmsg("Failed to delete appFamily $appId: " . mysql_error(), "red"); + +} + +function deleteAppVersion($versionId) +{ + $r = mysql_query("DELETE FROM appVersion WHERE versionId = $versionId"); + if($r) + addmsg("Application Version $versionId deleted", "green"); + else + addmsg("Failed to delete appVersion $versionId: " . mysql_error(), "red"); +} + + + +if($what) +{ + switch($what) + { + case "comment": + // delete a comment + //TODO + break; + case "category": + // delete category and the apps in it + deleteCategory($catId); + break; + case "appFamily": + // delete app family & all its versions + deleteAppFamily($appId); + break; + case "appVersion": + // delete a version + deleteAppVersion($versionId); + break; + } + + //FIXME need to redirect to the page before the confirmation page + redirect($apidb_root."appbrowse.php"); +} + + +?> diff --git a/admin/editAppFamily.php b/admin/editAppFamily.php new file mode 100644 index 0000000..5f986ea --- /dev/null +++ b/admin/editAppFamily.php @@ -0,0 +1,93 @@ +ownsApp($appId)) ) +{ + errorpage("Insufficient Privileges!"); + exit; +} + +apidb_header("Edit Application Family"); + +$t = new TableVE("edit"); + +if($cmd) +{ + $statusMessage = ''; + + //process add URL + if($cmd == "add_url") + { + $query = "INSERT INTO appData VALUES (null, $appId, 0, 'url', ". + "'$url_desc', '$url')"; + + if(debugging()) { echo "

query: $query

"; } + + if (mysql_query($query)) + { + //success + $statusMessage = "

The URL was successfully added into the database

\n"; + } + else + { + //error + $statusMessage = "

Database Error!
".mysql_error()."

\n"; + } + } + + // display status message + if ($statusMessage) + { + echo html_frame_start("Edit Application","300"); + echo "

$statusMessage

\n"; + echo html_frame_end(); + echo html_back_link(1,"editAppFamily.php?appId=$appId"); + } + +} +else if($HTTP_POST_VARS) +{ + // commit changes of form to database + $t->update($HTTP_POST_VARS); +} +else +{ + + // show form + $table = "appFamily"; + $query = "SELECT * FROM $table WHERE appId = $appId"; + + if(debugging()) { echo "

query: $query

"; } + + $t->edit($query); + + //url entry box + echo '
',"\n"; + echo html_frame_start("Add URL","400","",0); + echo '',"\n"; + + echo '',"\n"; + echo '',"\n"; + + echo '',"\n"; + + echo '
URL
Description
',"\n"; + echo html_frame_end(); + echo '',"\n"; + echo '
',"\n"; + + echo html_back_link(1,$apidb_root."appview.php?appId=$appId"); + +} + +apidb_footer(); + +?> diff --git a/admin/editAppNote.php b/admin/editAppNote.php new file mode 100644 index 0000000..c21765f --- /dev/null +++ b/admin/editAppNote.php @@ -0,0 +1,46 @@ +ownsApp($appId)) ) +{ + errorpage("Insufficient Privileges!"); + exit; +} + +apidb_header("Edit Application Note"); + +$t = new TableVE("edit"); + +if($HTTP_POST_VARS) +{ + // commit changes of form to database + $t->update($HTTP_POST_VARS); +} +else +{ + // show form + $table = "appNotes"; + $query = "SELECT * FROM $table WHERE noteId = $noteId"; + + if(debugging()) { echo "

query: $query

"; } + + $t->edit($query); + + echo html_back_link(1,$apidb_root."noteview.php?noteId=$noteId"); + +} + +apidb_footer(); + +?> diff --git a/admin/editAppOwners.php b/admin/editAppOwners.php new file mode 100644 index 0000000..37172cc --- /dev/null +++ b/admin/editAppOwners.php @@ -0,0 +1,120 @@ +\n"; + while($ob = mysql_fetch_object($result)) + { + echo "\n"; + } + echo "\n"; +} + + +if($cmd) +{ + if($cmd == "delete") + { + $result = mysql_query("DELETE FROM appOwners WHERE appId = $appId AND ownerId = $ownerId"); + if($result) + { + addmsg("Owner deleted", "green"); + redirectref(); + } + else + echo "Failed: " . mysql_error(); + } + if($cmd == "add") + { + $result = mysql_query("SELECT userid FROM user_list WHERE username = '$ownerName'"); + if($result) + { + $ob = mysql_fetch_object($result); + if(!$ob || !$ob->userid) + { + errorpage("Not Found!","User $ownerName was not found in the database"); + exit; + } + $result = mysql_query("INSERT INTO appOwners VALUES ($appId, $ob->userid)"); + if(!$result) + { + errorpage("Failed!",mysql_error()); + exit; + } + addmsg("Owner $ownerName added", "green"); + redirectref(); + } + else + echo "Failed: " . mysql_error(); + } +} +else +{ + apidb_header("Edit Application Owners"); + + $result = mysql_query("SELECT ownerId,username FROM appOwners, user_list WHERE appId = $appId AND userid = ownerId"); + + if($result && mysql_num_rows($result)) + { + echo html_frame_start("Current Owners","300",'',0); + echo "\n\n"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c = 1; + while($ob = mysql_fetch_object($result)) + { + //set row color + if ($c % 2 == 1) { $bgcolor = 'color0'; } else { $bgcolor = 'color1'; } + + $delete_link = "[delete]"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c++; + } + + echo "
User Name Delete
$ob->username  $delete_link  
\n\n"; + echo html_frame_end(); + + } + + echo "
\n"; + + echo html_frame_start("Manually Add User","300",'',5); + echo "\n"; + echo "\n"; + echo html_frame_end(); + + + echo html_frame_start("User List","",'',2); + build_user_list(); + echo html_frame_end(); + + echo "\n"; + echo "\n"; + echo "
\n"; + + apidb_footer(); +} + + +?> diff --git a/admin/editAppVersion.php b/admin/editAppVersion.php new file mode 100644 index 0000000..b03f3a7 --- /dev/null +++ b/admin/editAppVersion.php @@ -0,0 +1,111 @@ +ownsApp($appId)) ) +{ + errorpage("Insufficient Privileges!"); + exit; +} + +apidb_header("Edit Application Version"); + +$t = new TableVE("edit"); + + +if($cmd) +{ + $statusMessage = ''; + + //process screenshot upload + if($cmd == "screenshot_upload") + { + if(debugging()) + { + echo "

Screenshot: ($appId) file=$imagefile size=$imagefile_size\n"; + echo " name=$imagefile_name type=$imagefile_type
"; + } + + if(!copy($imagefile, "../data/screenshots/".basename($imagefile_name))) + { + // whoops, copy failed. do something + echo html_frame_start("Edit Application","300"); + echo "

debug: copy failed; $imagefile; $imagefile_name

\n"; + echo html_frame_end(); + echo html_back_link(1,"editAppVersion.php?appId=$appId&versionID=$versionId"); + apidb_footer(); + exit; + } + + $query = "INSERT INTO appData VALUES (null, $appId, $versionId, 'image', ". + "'".addslashes($screenshot_desc)."', '".basename($imagefile_name)."')"; + + if(debugging()) { echo "

query: $query

"; } + + if (mysql_query($query)) + { + //success + $statusMessage = "

The image was successfully added into the database

\n"; + } + else + { + //error + $statusMessage = "

Database Error!
".mysql_error()."

\n"; + if(debugging()) { $statusMessage .= "

$query

"; } + } + + } + + // display status message + if ($statusMessage) + { + echo html_frame_start("Edit Application","300"); + echo "

$statusMessage

\n"; + echo html_frame_end(); + echo html_back_link(1,"editAppVersion.php?appId=$appId&versionId=$versionId"); + } + +} +else if($HTTP_POST_VARS) +{ + $t->update($HTTP_POST_VARS); +} +else +{ + $table = "appVersion"; + $query = "SELECT * FROM $table WHERE appId = $appId AND versionId = $versionId"; + + if(debugging()) { echo "

query: $query

"; } + + $t->edit($query); + + + //image upload box + echo '
',"\n"; + echo html_frame_start("Upload Screenshot","400","",0); + echo '',"\n"; + + echo '',"\n"; + echo '',"\n"; + + echo '',"\n"; + + echo '
Image
Description
',"\n"; + echo html_frame_end(); + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '
',"\n"; + + echo html_back_link(1,$apidb_root."appview.php?appId=$appId&versionId=$versionId"); + +} + +apidb_footer(); + +?> diff --git a/admin/editBundle.php b/admin/editBundle.php new file mode 100644 index 0000000..ba0cd4b --- /dev/null +++ b/admin/editBundle.php @@ -0,0 +1,98 @@ +\n"; + while($ob = mysql_fetch_object($result)) + { + echo "\n"; + } + echo "\n"; +} + + +if($cmd) +{ + if($cmd == "delete") + { + $result = mysql_query("DELETE FROM appBundle WHERE appId = $appId AND bundleId = $bundleId"); + if($result) + addmsg("App deleted from bundle", "green"); + else + addmsg("Failed: " . mysql_error(), "red"); + } + if($cmd == "add") + { + $result = mysql_query("INSERT INTO appBundle VALUES ($bundleId, $appId)"); + if($result) + addmsg("App $appId added to Bundle $bundleId", "green"); + else + addmsg("Failed: " . mysql_error(), "red"); + } + redirectref(); + exit; +} +else +{ + apidb_header("Edit Application Bundle"); + + $result = mysql_query("SELECT bundleId, appBundle.appId, appName FROM appBundle, appFamily ". + "WHERE bundleId = $bundleId AND appFamily.appId = appBundle.appId"); + + if($result && mysql_num_rows($result)) + { + echo html_frame_start("Apps in this Bundle","300",'',0); + echo "\n\n"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c = 1; + while($ob = mysql_fetch_object($result)) + { + //set row color + if ($c % 2 == 1) { $bgcolor = 'color0'; } else { $bgcolor = 'color1'; } + + $delete_link = "[delete]"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c++; + } + + echo "
Application Name Delete
$ob->appName  $delete_link  
\n\n"; + echo html_frame_end(); + + } + + echo "
\n"; + + echo html_frame_start("Application List (double click to add)","",'',2); + build_app_list(); + echo html_frame_end(); + + echo "\n"; + echo "\n"; + echo "
\n"; + + apidb_footer(); +} + + +?> diff --git a/admin/editCategory.php b/admin/editCategory.php new file mode 100644 index 0000000..85fc771 --- /dev/null +++ b/admin/editCategory.php @@ -0,0 +1,42 @@ +update($HTTP_POST_VARS); +} +else +{ + $table = "appCategory"; + $query = "SELECT * FROM $table WHERE catId = $catId"; + + if(debugging()) + echo "$query

\n"; + + $t->edit($query); +} + +apidb_footer(); + +?> diff --git a/admin/editVendor.php b/admin/editVendor.php new file mode 100644 index 0000000..d80998d --- /dev/null +++ b/admin/editVendor.php @@ -0,0 +1,41 @@ +update($HTTP_POST_VARS); +} +else +{ + $table = "vendor"; + $query = "SELECT * FROM $table WHERE vendorId = $vendorId"; + + if(debugging()) + echo "$query

\n"; + + $t->edit($query); +} + +apidb_footer(); + +?> diff --git a/admin/index.php b/admin/index.php new file mode 100644 index 0000000..3d73fd7 --- /dev/null +++ b/admin/index.php @@ -0,0 +1,78 @@ +\n"; + echo "\n"; +} + +//desc +function make_options($name, $options, $label = "Submit") +{ + echo "\n"; +} + +//desc +if($table_cmd) +{ + apidb_header("Table Operation"); + $t = new TableVE("view"); + switch($table_cmd) + { + case "check": + $t->view("CHECK TABLE $table_id"); + break; + case "describe": + $t->view("DESCRIBE $table_id"); + break; + case "optimize": + $t->view("OPTIMIZE TABLE $table_id"); + break; + } + apidb_footer(); + exit; +} + +// output of admin page begins here +apidb_header("Admin"); + +// Draw User List +include(BASE."include/"."query_users.php"); + + +apidb_footer(); + +?> diff --git a/admin/path.php b/admin/path.php new file mode 100644 index 0000000..8e1d095 --- /dev/null +++ b/admin/path.php @@ -0,0 +1,3 @@ + diff --git a/apidb.css b/apidb.css new file mode 100644 index 0000000..aee6462 --- /dev/null +++ b/apidb.css @@ -0,0 +1,160 @@ +/* Body Document Defaults */ +BODY { background-color: #E2E2E2; + color: #000000; margin: 0; } + +/* Link Colors */ +A { color: #A50D0D; } +A:visited { color: #FF0000; } +A:hover { color: #FF6666; text-decoration: underline; } +A:active { color: #FF0000; } +A.hidden { text-decoration: none; color: #000000; } + +OL,UL,P,BODY { font-family: Helvetica, Arial; font-size: 10pt; } +TD,TR,TH,FORM { font-family: Helvetica, Arial; font-size: 10pt; } +SPAN { font-family: Helvetica, Arial; font-size: 10pt; } +H1,H2,H3 { font-family: Helvetica, Arial; font-size: 14pt; } +H4,H5,H6 { font-family: Helvetica, Arial; font-size: 12pt; } +INPUT { font-family: Helvetica, Arial; font-size: 10pt; } +PRE,T1 { font-family: Helvetica, Arial; font-size: 10pt; } +SMALL { font-family: Helvetica, Arial; font-size: 8pt; } + +TD.cline { background-color: #EEEEEE; color: #000000; + text-align: center; font-weight: bold; font-size: 10pt; } + +TH.qheader { background-color: #C3C8E5; color: #555555; font-size: 10pt; } +TR.qheader { background-color: #C3C8E5; color: #555555; font-size: 10pt; } + +TABLE.bg { background-color: #FF6666; color: #FFFFFF } +TABLE.bg2 { background-color: #E0E0E0; } +TD.bg2 { background-color: #E0E0E0; } + +TD.line1 { background-color: #E7E7E7; } +TD.line2 { background-color: #C0C0C0; color: #505050; font-size: 8pt; } +TD.line3 { background-color: #6F6F6F; } +TR.line1 { background-color: #E7E7E7; } +TR.line2 { background-color: #C0C0C0; color: #505050 } +TR.line3 { background-color: #6F6F6F; } + + +TH.titlex { background-color: #BBC2E5 } +TH.title { background-color: #C0C0C0; font-weight: bold } +TD.title { background-color: #C0C0C0; font-weight: bold } +TD.btitle { background-color: #FFFFFF } + +TH.sqtitle { background-color: #C3C8E5; color: #555555 } + + +TR.buttons { background-color: #BDDAE5 } +TD.button { background-color: #BDDAE5 } +TD.button2 { background-color: #ABB2D5; } + +/* query row colors */ +.color0 { background-color: #E0E0E0 } +.color1 { background-color: #C0C0C0 } +.color2 { background-color: #FFFFFF } +.color3 { background-color: #666666 } +.color4 { background-color: #999999 } + +/* box */ +.box-title { background-color: #AAAAAA; color: #FFFFFF; font-weight: bold } +.box-label { background-color: #C0C0C0 } +.box-body { background-color: #E0E0E0 } + +/* labels */ +TD.label { font-weight: bold } + +/* for inwine/intwine */ +TD.yes { color: #00B100; font-weight: italic; text-align: center } +TD.no { color: #B10000; font-weight: italic; text-align: center } +TD.stub { color: #0000B1; font-weight: italic; text-align: center } + + +/* Copyright Notice */ +.copyright { font-family: Helvetica, Arial; font-size: 8pt; color: #6F6F6F; } + + +/* Rating Number */ +.rating { font-family: Helvetica, Arial; font-size: 6pt; color: #333333; } + + +/* background colors */ +.vltgrey { background-color: #f9f9f9; } +.ltgrey { background-color: #EFEFEF; } +.grey { background-color: #C0C0C0; } +.white { background-color: #FFFFFF; } +.dkgrey { background-color: #888888; } +.ltblack { background-color: #999999; } +.black { background-color: #000000; } +.blueish { background-color: #bed5f7; } + +/* text colors */ +.inverse { color: #FFFFFF; } +.disabled { color: #999999; } +.normal { color: #000000; } +.error { color: #ff0000; } +.water { color: #6060ff; } +.good { color: #60ff60; } +.warning { color: #fffa00; } +.blueman { color: #335184; } + +/* text styles */ +.strike { text-decoration: line-through; } +.bold { font-weight: bold; } +.newstitle { font-size: 14px; font-weight: bold; color: #000000; } + +/* Menu Config */ +.menuTitle { font-size: 12px; color: #ffffff; font-weight: bold; text-decoration: none; } +.menuTitle:visited { font-size: 12px; color: #ffffff; font-weight: bold; text-decoration: none; } +.menuTitle:hover { font-size: 12px; color: #ffffff; font-weight: bold; text-decoration: none; } +.menuLink { font-size: 10px; color: #ffffff; font-weight: bold; } +.menuItem { font-size: 10px; color: #000000; } +.menuItem:visited { font-size: 10px; color: #000000; } +.menuItem:hover { font-size: 10px; color: #A50D0D; } + +.topMenu { background-color: #601919; } +.sideMenu { background-color: #FFFFFF; } +.border { background-color: #601919; } + +/* Misc */ +.tiny { font-size: 6pt; } +.small { font-size: 8pt; } +.big { font-size: 14pt; } + +/* Generic Buttons */ +.button { background-color: #6b86bb; color: #ffffff; font-family: Helvetica, Arial, Sans-Serif; font-size: 10pt; + padding: 0; } +.searchInput { background-color: #FFFFFF; color: #000000; font-family: Helvetica, Arial, Sans-Serif; font-size: 10pt; + padding: 0; } + +/* Note Blip */ +.blip { color: #ff0000; font-size: 8pt; } + +/* Footer */ +.footer { font-size: 8pt; color: #777777; } + +/* Footer Link */ +.footerLink { font-family: Helvetica, Arial; font-size: 8pt; color: #666666; } + + +/* Generic Buttons */ +.button { background-color: #666666; color: #ffffff; font-family: Helvetica, Arial; font-size: 10pt; + groove #000000; padding: 0; } + + +/* Vote Button */ +.votebutton { background-color: #666666; color: #ffffff; font-family: Helvetica, Arial; font-size: 8pt; + groove #000000; padding: 0; } + + +/* Rate Button */ +.ratebutton { background-color: #666666; color: #ffffff; font-family: Helvetica, Arial; font-size: 8pt; + groove #000000; padding: 0; } + + +/* Search Button */ +.searchbutton { background-color: #666666; color: #ffffff; font-family: Helvetica, Arial; font-size: 10pt; + groove #000000; padding: 0; } + +/* Search Field */ +.searchfield { background-color: #EOEOEO; color: #666666; font-family: Helvetica, Arial; font-size: 10pt; + groove #000000; padding: 0; } diff --git a/appbrowse.php b/appbrowse.php new file mode 100644 index 0000000..8e408bb --- /dev/null +++ b/appbrowse.php @@ -0,0 +1,140 @@ +add("Edit this Category", $apidb_root."admin/editCategory.php?catId=$catId"); + $url = $apidb_root."admin/deleteAny.php?what=category&catId=$catId&confirmed=yes"; + $m->add("Delete this Category", "javascript:deleteURL(\"Are you sure?\", \"".$url."\")"); + + + $m->done(); +} + +if(!$catId) + $catId = 0; // ROOT + +// list sub categories +$cat = new Category($catId); +$catFullPath = make_cat_path($cat->getCategoryPath()); +$subs = $cat->getCategoryList(); + +//display admin box +if(havepriv("admin") && $catId != 0) + apidb_sidebar_add("admin_menu"); + +//output header +apidb_header("Browse Applications"); + +if($subs) +{ + echo html_frame_start("",'98%','',2); + echo "

Category: ". $catFullPath ."
\n"; + echo html_frame_end(); + + echo html_frame_start("","98%","",0); + echo "\n\n"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c = 0; + while(list($id, list($name, $desc)) = each($subs)) + { + //set row color + $bgcolor = ($c % 2 == 0) ? "color0" : "color1"; + + //get number of apps + $appcount = $cat->getAppCount($id); + + //format desc + $desc = substr(stripslashes($desc),0,70); + + //display row + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c++; + } + + echo "
Sub CategoryDescriptionNo. Apps
".stripslashes($name)."$desc  $appcount  
\n\n"; + echo html_frame_end("$c categories"); +} + + + +// list applications in this category +$apps = $cat->getAppList($catId); +if($apps) +{ + echo html_frame_start("",'98%','',2); + echo "

Category: ". $catFullPath ."
\n"; + echo html_frame_end(); + + echo html_frame_start("","98%","",0); + echo "\n\n"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c = 0; + while(list($id, list($name, $desc)) = each($apps)) + { + //skip if a NONAME + if ($ob->appName == "NONAME") { continue; } + + //set row color + $bgcolor = ($c % 2 == 0) ? "color0" : "color1"; + + //get number of versions + $query = mysql_query("SELECT count(*) as versions FROM appVersion WHERE appId = $id AND versionName != 'NONAME'"); + $ob = mysql_fetch_object($query); + + //format desc + $desc = substr(stripslashes($desc),0,70); + + //display row + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c++; + } + + echo "
Application NameDescriptionNo. Versions
".stripslashes($name)."$desc  $ob->versions  
\n\n"; + echo html_frame_end("$c applications in this category"); +} + +// Disabled for now +//if ($catId != 0) +//{ +// log_category_visit($cat->id); +//} + +echo p(); + +apidb_footer(); + +?> diff --git a/appimage.php b/appimage.php new file mode 100644 index 0000000..14aa9c5 --- /dev/null +++ b/appimage.php @@ -0,0 +1,96 @@ +url)) + $url = "data/screenshots/$ob->url"; +else + $url = $ob->url; + +if(eregi(".+\\.(jpg|jpeg)$", $url)) + $type = "jpeg"; +else +if(eregi(".+\\.(png)$", $url)) + $type = "png"; + +if(!$type) + handle_error("Unknown Image Type"); + +if($type == "png") + $im = ImageCreateFromPNG($url); +else +if($type == "jpeg") + $im = ImageCreateFromJpeg($url); + +if(!$im) + handle_error("Error"); + +if($width && $height) { + // do scaling + $sim = ImageCreate($width, $height); + ImageCopyResized($sim, $im, 0, 0, 0, 0, $width, $height, ImageSX($im), ImageSY($im)); + $im = $sim; +} + +// output the image +if($type == "png") +{ + header("Content-type: image/png"); + ImagePNG($im); +} +else +if($type == "jpeg") +{ + header("Content-type: image/jpeg"); + ImageJPEG($im); +} + +?> diff --git a/appsubmit.php b/appsubmit.php new file mode 100644 index 0000000..a517134 --- /dev/null +++ b/appsubmit.php @@ -0,0 +1,85 @@ +lookup_email($current->userid); +} + +//header +apidb_header("Submit Application"); + + +if ($queueName) +{ + // add to queue + + //FIXME: need to get image upload in + + $query = "INSERT INTO appQueue VALUES (null, '". + addslashes($queueName)."', '". + addslashes($queueVersion)."', '". + addslashes($queueVendor)."', '". + addslashes($queueDesc)."', '". + addslashes($queueEmail)."', '". + addslashes($queueURL)."', '". + addslashes($queueImage)."');"; + + mysql_query($query); + + + if ($error = mysql_error()) + { + echo "

Error:

\n"; + echo "

$error

\n"; + } + else + { + echo "

Your application has been submitted for Review. You should hear back\n"; + echo "soon about the status of your submission

\n"; + } + +} +else +{ + // show add to queue form + + echo '
',"\n"; + + echo "

This page is for submitting new applications to be added to this\n"; + echo "database. The application will be reviewed by the AppDB Administrator\n"; + echo "and you will be notified via email if this application will be added to\n"; + echo "the database.

\n"; + echo "

Please don't forget to mention whether you actually tested this\n"; + echo "application under Wine, which Wine version you used and how well it worked. Thank you !

\n"; + echo "

To submit screenshots, please email them to "; + echo "appdb@winehq.com

\n"; + + echo html_frame_start("New Application Form",400,"",0); + + echo "\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + //echo '',"\n"; + echo '',"\n"; + echo '
App Name
App Version
App Vendor
App URL
App Desc
Email
Image
',"\n"; + + echo html_frame_end(); + + echo "
"; +} +apidb_footer(); + +?> diff --git a/appview.php b/appview.php new file mode 100644 index 0000000..b884d01 --- /dev/null +++ b/appview.php @@ -0,0 +1,420 @@ +add("Add Note", $apidb_root."admin/addAppNote.php?appId=$appId&versionId=$versionId"); + $m->addmisc(" "); + + $m->add("Edit Version", $apidb_root."admin/editAppVersion.php?appId=$appId&versionId=$versionId"); + + $url = $apidb_root."admin/deleteAny.php?what=appVersion&versionId=$versionId&confirmed=yes"; + $m->add("Delete Version", "javascript:deleteURL(\"Are you sure?\", \"".$url."\")"); + + } + else + { + $m->add("Add Version", $apidb_root."admin/addAppVersion.php?appId=$appId"); + $m->addmisc(" "); + + $m->add("Edit App", $apidb_root."admin/editAppFamily.php?appId=$appId"); + + // global admin options + if(havepriv("admin")) + { + $url = $apidb_root."admin/deleteAny.php?what=appFamily&appId=$appId&confirmed=yes"; + $m->add("Delete App", "javascript:deleteURL(\"Are you sure?\", \"".$url."\")"); + $m->addmisc(" "); + $m->add("Edit Owners", $apidb_root."admin/editAppOwners.php?appId=$appId"); + $m->add("Edit Bundle", $apidb_root."admin/editBundle.php?bundleId=$appId"); + } + + } + + $m->done(); +} + + +function get_screenshot_img($appId, $versionId) +{ + global $apidb_root; + + if(!$versionId) + $versionId = 0; + + $result = mysql_query("SELECT * FROM appData WHERE appId = $appId AND versionId = $versionId AND type = 'image'"); + + if(!$result || !mysql_num_rows($result)) + { + $imgFile = "No Screenshot"; + } + else + { + $ob = mysql_fetch_object($result); + $imgFile = "$ob->description"; + } + + $img = html_frame_start("",'128','',2); + $img .= "$imgFile"; + $img .= html_frame_end()."
"; + + return $img; +} + + +function display_catpath($catId) +{ + $cat = new Category($catId); + + $catFullPath = make_cat_path($cat->getCategoryPath()); + echo html_frame_start("",'98%','',2); + echo "

Category: ". $catFullPath ."
\n"; + echo html_frame_end(); +} + +/* display the SUB apps that belong to this app */ +function display_bundle($appId) +{ + $result = mysql_query("SELECT appFamily.appId, appName, description FROM appBundle, appFamily ". + "WHERE bundleId = $appId AND appBundle.appId = appFamily.appId"); + if(!$result || mysql_num_rows($result) == 0) + { + // do nothing + return; + } + + echo html_frame_start("","98%","",0); + echo "\n\n"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c = 0; + while($ob = mysql_fetch_object($result)) + { + //set row color + $bgcolor = ($c % 2 == 0) ? "color0" : "color1"; + + //format desc + $desc = substr(stripslashes($ob->description),0,50); + if(strlen($desc) == 50) + $desc .= " ..."; + + //display row + echo "\n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c++; + } + + echo "
Application NameDescription
".stripslashes($ob->appName)."$desc  
\n\n"; + echo html_frame_end(); +} + + +/* display the notes for the app */ +function display_notes($appId, $versionId = 0) +{ + $result = mysql_query("SELECT noteId,noteTitle FROM appNotes ". + "WHERE appId = $appId AND versionId = $versionId"); + + if(!$result || mysql_num_rows($result) == 0) + { + // do nothing + return; + } + + echo " Notes\n"; + + $c = 1; + while($ob = mysql_fetch_object($result)) + { + //skip if NONAME + if ($ob->noteTitle == "NONAME") { continue; } + + //set link for version + if ($versionId != 0) + { + $versionLink = "&versionId=$versionId"; + } + + //display row + echo " $c. ".substr(stripslashes($ob->noteTitle),0,30)."
\n"; + $c++; + } + + echo "\n"; +} + +/* display the versions */ +function display_versions($appId, $versions) +{ + if ($versions) + { + + echo html_frame_start("","98%","",0); + echo "\n\n"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c = 0; + while(list($idx, $ver) = each($versions)) + { + //set row color + $bgcolor = ($c % 2 == 0) ? "color0" : "color1"; + + //format desc + $desc = substr(stripslashes($ver->description),0,75); + if(strlen($desc) == 75) + $desc .= " ..."; + + //get ratings + $r_win = rating_stars_for_version($ver->versionId, "windows"); + $r_fake = rating_stars_for_version($ver->versionId, "fake"); + + //count comments + $r_count = count_comments($appId,$ver->versionId); + + //display row + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c++; + } + + echo "
VersionDescriptionRating With WindowsRating Without WindowsComments
".$ver->versionName."$desc  $r_win$r_fake$r_count
\n"; + echo html_frame_end("Click the Version Name to view the details of that Version"); + } +} + +/* code to VIEW an application & versions */ + +if($appId && !$versionId) +{ + $app = new Application($appId); + $data = $app->data; + if(!$data) { + // Oops! application not found or other error. do something + errorpage('Internal Database Access Error'); + exit; + } + + // Show Vote Menu + if(loggedin()) + apidb_sidebar_add("vote_menu"); + + // Show Admin Menu + if(loggedin() && (havepriv("admin") || $current->ownsApp($appId))) { + apidb_sidebar_add("admin_menu"); + } + + // header + apidb_header("Viewing App - ".$data->appName); + + //cat display + display_catpath($app->data->catId); + + //set Vendor + $vendor = $app->getVendor(); + + //set URK + $appLinkURL = ($data->webPage) ? "".substr(stripslashes($data->webPage),0,30)."": " "; + + //set Image + $img = get_screenshot_img($appId, $versionId); + + //start display application + echo html_frame_start("","98%","",0); + + echo '',"\n"; + echo '',"\n"; + echo "\n"; + echo "\n"; + echo "\n"; + + //display notes + display_notes($appId); + + //main URL + echo "\n"; + + //optional links + $result = mysql_query("SELECT * FROM appData WHERE appId = $appId AND type = 'url'"); + if($result && mysql_num_rows($result) > 0) + { + echo "\n"; + } + + // display app owner + $result = mysql_query("SELECT * FROM appOwners WHERE appId = $appId"); + if($result && mysql_num_rows($result) > 0) + { + echo "\n"; + } + + echo "
Name ".stripslashes($data->appName)."
App Id ".$data->appId."
Vendor ". + " ".stripslashes($vendor->vendorName)."  \n"; + echo "
URL".$appLinkURL."
Links\n"; + while($ob = mysql_fetch_object($result)) + { + echo " ".substr(stripslashes($ob->description),0,30)."
\n"; + } + echo "
Owner\n"; + while($ob = mysql_fetch_object($result)) + { + $inResult = mysql_query("SELECT username,email FROM user_list WHERE userid = $ob->ownerId"); + if ($inResult && mysql_num_rows($inResult) > 0) + { + $foo = mysql_fetch_object($inResult); + echo " ".substr(stripslashes($foo->username),0,30)."
\n"; + } + } + echo "
\n"; + + //Desc + echo "
Description
\n"; + echo add_br(stripslashes($data->description)); + + echo "
\n"; + + echo html_frame_end("For more details and user comments, view the versions of this application."); + + //display versions + display_versions($appId,$app->getAppVersionList()); + + //display bundle + display_bundle($appId); + + // disabled for now + //log_application_visit($appId); + +} +else if($appId && $versionId) +{ + $app = new Application($appId); + $data = $app->data; + + if(!$data) { + // Oops! application not found or other error. do something + errorpage('Internal Database Access Error'); + exit; + } + + // rating menu + if(loggedin()) { + apidb_sidebar_add("rating_menu"); + } + + // admin menu + if(loggedin() && (havepriv("admin") || $current->ownsApp($appId))) { + apidb_sidebar_add("admin_menu"); + } + + // header + $ver = $app->getAppVersion($versionId); + apidb_header("Viewing App Version - ".$data->appName); + + //cat + display_catpath($app->data->catId); + + //set URL + $appLinkURL = ($data->webPage) ? "".substr(stripslashes($data->webPage),0,30)."": " "; + + //set image + $img = get_screenshot_img($appId, $versionId); + + //start version display + echo html_frame_start("","98%","",0); + + echo '',"\n"; + echo '',"\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + + //Rating Area + $r_win = rating_stars_for_version($versionId, "windows"); + $r_fake = rating_stars_for_version($versionId, "fake"); + + echo "\n"; + + //notes + display_notes($appId, $versionId); + + //Image + echo "\n"; + + echo "
Name".stripslashes($data->appName)."
Ver Id $ver->versionId
Version".stripslashes($ver->versionName)."
URL".stripslashes($appLinkURL)."
Rating $r_win \n"; + echo "
$r_fake
$img
\n"; + + //Desc Image + echo "
Description
\n"; + echo add_br(stripslashes($ver->description)); + echo "
\n"; + + echo html_frame_end(); + + //TODO: code to view/add user experience records + if(!$versionId) { + $versionId = 0; + } + + // Comments Section + view_app_comments($appId, $versionId); + +} +else +{ + // Oops! Called with no params, bad llamah! + errorpage('Page Called with No Params!'); + exit; +} + +echo p(); + +apidb_footer(); + +?> diff --git a/banner/468x60/cw-ad01.gif b/banner/468x60/cw-ad01.gif new file mode 100644 index 0000000000000000000000000000000000000000..b4328e965d750414958991718d041cdcb6ae78de GIT binary patch literal 13337 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�SIrb)rs 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 NyYlnZci0&jtO0?c%AEiJ literal 0 HcmV?d00001 diff --git a/banner/468x60/cw-ad02.gif b/banner/468x60/cw-ad02.gif new file mode 100644 index 0000000000000000000000000000000000000000..e70660be5809cbcc651c9b35cda9fa22ab35f954 GIT binary patch literal 11594 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

k_0`$|S8`Lrd|YAqgivE53t*zh3LlvC^cPNnMx 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

Tzw1XMcab3@qnY#(#-sT+u2{5i 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 X%5w1;@wK;ht&Iy>79qgGz+epknOJ@= literal 0 HcmV?d00001 diff --git a/banner/468x60/cw-ad04.gif b/banner/468x60/cw-ad04.gif new file mode 100644 index 0000000000000000000000000000000000000000..3c648ffb286714284771263fd654df664a906f10 GIT binary patch literal 18875 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 JQb_>@YXB#xRNepp literal 0 HcmV?d00001 diff --git a/banner/xml/cw-ad01.xml b/banner/xml/cw-ad01.xml new file mode 100644 index 0000000..d5c9223 --- /dev/null +++ b/banner/xml/cw-ad01.xml @@ -0,0 +1,7 @@ + + + + cw-ad04 + http://www.codeweavers.com/products/crossover/?ad=1 + QuickTime for Linux! + diff --git a/banner/xml/cw-ad02.xml b/banner/xml/cw-ad02.xml new file mode 100644 index 0000000..321b43c --- /dev/null +++ b/banner/xml/cw-ad02.xml @@ -0,0 +1,7 @@ + + + + cw-ad04 + http://www.codeweavers.com/products/crossover/support_wine.php?ad=1 + Support the Wine Project! + diff --git a/banner/xml/cw-ad04.xml b/banner/xml/cw-ad04.xml new file mode 100644 index 0000000..2c1efdb --- /dev/null +++ b/banner/xml/cw-ad04.xml @@ -0,0 +1,7 @@ + + + + cw-ad04 + http://www.codeweavers.com/products/office/?ad=1 + Microsoft Office On Linux! + diff --git a/commentview.php b/commentview.php new file mode 100644 index 0000000..31c061a --- /dev/null +++ b/commentview.php @@ -0,0 +1,21 @@ + diff --git a/edituser.php b/edituser.php new file mode 100644 index 0000000..0c45eac --- /dev/null +++ b/edituser.php @@ -0,0 +1,55 @@ +update($HTTP_POST_VARS); +} +else +{ + $qc = new qclass(); + $qc->add_fields(make_fields($user_fields, "user_list")); + if($username) + $qc->add_where("username = '$username'"); + else + $qc->add_where("userid = $userid"); + $qc->resolve(); + + $query = $qc->get_query(); + + if(debugging()) + echo "$query

\n"; + + $t->edit($query); +} + +apidb_footer(); + +?> diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..6b8f92865f09027d3a94f2266a30f4ef0ebdd635 GIT binary patch literal 3638 zcmZQzU}Ruo5D;JhgA7&%1~mo-1_cE$mth4514ADx1A_(w0|Q72NSKj<11#yl2&Nze zl>Ptze})g=KQKIa{(#~B{re0Tu3um{aQpzn{vG=nHf-3yuztmQh6M{2FwCDZpJBp; z2@L%m{R|4~^BEM>Com|egV+rW_4V}(1r-Gh`33n52^k3t@d@z^0TBTV{sI0B4jv8+ z_73(83hD(6^707`^78Qv^6~);0^$w~2Ilq*`uh3|3hD|B0^;@z^78r&0^<4%{QL?G z^78Tw0^$M;{QU9^{QUe34D9@1cW=lDU|65v&#*qifnh;_1H*ie0)`0=Ae_Lkz{7xH zzJoqPzj*;ezkUHjgF1*#VCdHmU}%tcVCdJkXXsbAXP96v&oDtx3ityU3iv^^14BN4JVSxFJ=m?I#ApZ%<`4ko{eK|9Bd(??24ejC_m4+i zTU%ROkps%r*4Eb4)`syQg6!IC5C)7Ck%Y0Jv^F=C0in1wWaUI5Ofad$$IHhn2RBrZ zkC&H^k5>jJAOzy`^75*J761FkE&!6|fp3TW~1N=ftc^2tKoA*{m6z`(#FudE4G zAOa0`W=@Czs1yVVF+m;5#?8RM$RR2A@81vm|Nk56|Nm$F|NsBT|NsC0{Qv*|pa1{= zgT#OE|NsAi9g3O%|Np@V!G9S3{|95{|NlYdEXZ^R22i;SDQ6p4Kz2bfw48CxMSxt zwQJWhY~8w*Vej6(49AWgW4Lzh8pFMN_ZXf(f6nmz`*#LVnj6LcN5kR&@CbtszyC8V zS+Ibip#hY!|1&WBXJB9e`3*!dfcyyJf&?KY00V=yiMEQY5I--!I!pvk+kDqmfHZSJ zEjmlMIGAB$q6C*?;L@}L3&II&O04{7T$-r-eOA;h*#mis;qH$tv22g>CQ<}k=m%#+LECa}Wyk__mfZVTuTZIL; zprV?ZqBMFCLXET*QZqL-H#ara7gWdQQ3W|uQ&V$OkP<~M%#gI?21%QPRG6A-@S{Z{ z1H%tNkWO=u0&{ay4Iy+Bv_&CuP&*VQ(cEAl4AT!b!cTW1y#sk&~B0!Eb)klkM zYi>h`+sr|JG&eVuQ-bP*QVJmNn}Q67m|@I=8k8m=3(QURwY2n&!Dgs&p*m4W!(3lV z#=y+%hq|5G(KWLM@fjHYAK?H0gMt750S5d342=K(Gcf=E&&2-!|NrLy|NkHU|NsBv z|Ns9#{Qv*|2N1UZ|NjB||NjRV|NlS0@c(}UL;e2-2K)aF4DwLS|Gxoj82kSN49x!@ cfHC9$2Mmn=KQJ(W@ec-u{}9an{||#b0HGN(@Bjb+ literal 0 HcmV?d00001 diff --git a/help/.cvsignore b/help/.cvsignore new file mode 100644 index 0000000..55d2fba --- /dev/null +++ b/help/.cvsignore @@ -0,0 +1,2 @@ +stderr + diff --git a/help/appdb_faq.help b/help/appdb_faq.help new file mode 100644 index 0000000..63aceda --- /dev/null +++ b/help/appdb_faq.help @@ -0,0 +1,66 @@ + + +

Application Database FAQ

+ +

This FAQ answers questions related to the usage of the +Application Database.

+ +
+ +If you have more questions you would like to add to our FAQ, please contact us +at appdb@winehq.com. + +

 

+ diff --git a/help/generic.help b/help/generic.help new file mode 100644 index 0000000..251f585 --- /dev/null +++ b/help/generic.help @@ -0,0 +1,54 @@ + + +This is meant as generic instructions in case an AppDB entry +for a certain program doesn't exist. + +
    + +
  1. Make sure your Wine release is pretty recent. +Current possibilities are:
  2. + +

      +
    • CodeWeavers Wine Preview + simple, complete configuration
    • +
    • TransGaming WineX, + Wine version with special DirectX support, use this one for games.
    • +
    • Misc. Wine packages/versions downloadable via + WineHQ
    • +
    +

    + +

  3. Run winecheck +(chmod +x winecheck; ./winecheck) +to verify the most important aspects of Wine environment +configuration
  4. + +

  5. Run your program
  6. + +

  7. In case of failure, try different builtin, native DLL settings: +Run Wine with --debugmsg +loaddll to find out which +DLLs are loaded as native or builtin ones. +Then make sure appropriate native versions are in the +c:\windows\system directory as configured in your wine +config file, and then use either --dll DLL1, DLL2,...=n or +--dll DLL1,DLL2,...=b +to use native or builtin setting for certain DLLs, respectively.
  8. + +

  9. In case of persisting failure, check out +Wine Troubleshooting Guide +and read all of the available documentation at +WineHQ Support
  10. + +

  11. If that doesn't help, then ask people on +irc.openprojects.net +channel #WineHQ or on the +wine-users +mailing list.
  12. + +

  13. If you have more questions, please contact us +at appdb@codeweavers.com.
  14. + +

+ +

 

+ diff --git a/help/index.php b/help/index.php new file mode 100644 index 0000000..b80876f --- /dev/null +++ b/help/index.php @@ -0,0 +1,102 @@ +Providing all the help you need 24x7


\n"; + + echo "
    \n"; + + // read dir + $files = array(); + $d = opendir($help_path); + while($entry = readdir($d)) + { + array_push($files, $entry); + } + closedir($d); + + //sort dir + sort($files); + + // display dir + while (list($key,$file) = each($files)) + { + if(!ereg("(.+)\\.help$", $file, $arr)) + continue; + + $id = $arr[1]; + $title = get_help_title("$help_path/$file"); + + echo "
  • $title
  • \n"; + } + + echo "


\n"; + + echo "

Need more help? Contact us at appdb@winehq.com

\n"; + + apidb_footer(); +} + +function display_help ($topic) +{ + global $help_path; + + $file = "$help_path/$topic.help"; + $title = get_help_title($file); + + if(! $title) { + $title = "Help on $topic"; + } + + apidb_header($title); + if(file_exists($file)) { + include($file); + } else { + echo "

No help available on that topic

\n"; + } + + apidb_footer(); +} + +function get_help_title ($file) +{ + $fp = @fopen($file, "r"); + if(!$fp) + return null; + + $line = fgets($fp, 1024); + if(!$line) + return null; + + $line = trim($line); + + if(eregi("^$", $line, $arr)) + { + return $arr[1]; + } + return "Internal Error: missing title"; +} + +?> diff --git a/help/path.php b/help/path.php new file mode 100644 index 0000000..8e1d095 --- /dev/null +++ b/help/path.php @@ -0,0 +1,3 @@ + diff --git a/help/privacy.help b/help/privacy.help new file mode 100644 index 0000000..16dc8bb --- /dev/null +++ b/help/privacy.help @@ -0,0 +1,45 @@ + + +

Application DB Privacy Policy

+ +

+CodeWeavers is decidated to the privacy of its customers.
+

    + Whatever specific information you give to us will be used only to enable user + specific features of the Application Database. We will give your information + to no third parties, nor will we send you email you did not request. We may + use your information in the aggregate to better understand our market. +
+

+ +

+Cookies +

    + The Application Database uses cookies only to preserve login information in your web browser. + Advertisers or other companies do not have access to the AppDB's cookies. +
+

+ +

+Changes to this Privacy Policy
+

    + We may amend this policy from time to time. If we make any + substantial changes in the way we use your personal information we + will notify you by posting a prominent announcement on our pages. +
+

+ +

+Questions or Suggestions
+

    + If you have questions or suggestions, feel free to contact us at + appdb@winehq.com +
+

+ +

+NOTICE: Click here +for important information about safe surfing from the Federal Trade Commission. +

+ +

 

diff --git a/help/ratings.help b/help/ratings.help new file mode 100644 index 0000000..fcc7536 --- /dev/null +++ b/help/ratings.help @@ -0,0 +1,95 @@ + + +

Application Ratings System Help

+ +

+The Application Database features a rating system that allows us and you to see +which applications work the best in Wine. This voting system is designed to be +pessimistic. +

+ +
    + +
  1. Log into the Application Database.
  2. + +

  3. Browse to the Application you wish to rate.
  4. + +

  5. In the sidebar, choose whether you are rating Wine running + in Windows mode, or Fake Windows Mode.
    +
      +
    • With Windows With Windows = Wine Configured to use a Windows partition.
    • +
    • Without Windows Without Windows = Wine using its own internal Windows (Fake Windows).
    • +
    +
  6. + +

  7. In the sidebar, click the number of stars you want to + rate this application.
    +
      +
    • 0 -- Unrated. +
    • 1 -- Totally nonfunctional. Crashes on load. +
    • 2 -- Partial functionality. Good enough for a carefully scripted demo. +
    • 3 -- Sufficient functionality for noncritical work. Occasional crashes okay, + as are weird setup problems, required patches, or missing major functionality. + Alpha quality. +
    • 4 -- Substantially correct. Good enough for general use, with possible + caveats. +
    • 5 -- Perfect. No flaws under any mode +
    +
  8. + +

  9. Click the Rate! button to store your vote for this + application. +
  10. + +

+ + + How to rate an application
+ +Please don't exaggerate how well things work. +It only creates expectations which +can't be met, and doesn't do anybody +any good in the long run. +Here is a simple flowchart for testing applications. + +
    + +
  • First, figure out the name of the app, the vendor, and the product + version number.
  • + +

  • Try to start the application under the emulator. + If it completes loading, + without crashing, and displaying more or less what it would under + some version of Windows, then the app deserves a 2. Otherwise, it gets a + 1.
  • + +

  • Try doing a few things with it. If you can + find several useful operations + which can be correctly performed with the app, such that you would be + willing to stand in front of a large group of people, saying ``This app + works nearly perfectly on Wine'' and doing those operations, give it a 3. +
  • + +

  • If you don't normally use the app, stop here. Higher ratings should + only be given for app performance under actual use.
  • + +

  • At some time when there is something which you need to do with the + app, try doing it under Wine. If you can get the job done without putting + your fist through the screen, then the application deserves a 4. Note that + this is not, ``Someone could do useful work with this app'' but + ``I have used this app for useful work, not just fooling around.''
  • + +

  • If you use an app under Wine for months, and its behavior is robust + under a variety of uses, its performance is adequate, and + these characteristics are stable as Wine changes from release to release, + and it works for a lot of people with varying setups under various OSes, + then it deserves a 5.
  • + +

  • After a new version of Wine, test the application again. If the app + improves or gets worse, come back and change your vote.
  • + +

+ +Remember: only you can prevent rating inflation. + +

 

diff --git a/help/voting.help b/help/voting.help new file mode 100644 index 0000000..30964fe --- /dev/null +++ b/help/voting.help @@ -0,0 +1,40 @@ + + +

Application Voting System Help

+ +

+The Application Database features a voting system that allows you to pick which 3 applications +you would MOST like to see running in Wine. +

+ +

Step by Step on Voting

+
    + +
  1. Log into the Application Database.
  2. + +

  3. Browse to the Application you wish to add to your vote list.
  4. + +

  5. In the sidebar, Click one of the 3 available slots, and click Vote.
  6. + +

  7. Done!
  8. + +
+ + +

Voting System Notes

+ +
    + +
  • Please seriously only vote for applications which will benefit the community. Don't + vote for applications that are known to work well. We know Solitaire works. Voting for it + would not make much sense.
  • + +

  • When voting for an application, you are voting for ALL its various versions. There is + a separate system in place for ranking versions.
  • + +

  • You can clear your vote at anytime. Simply browse to any App in the database, select the app + in your vote list you want to clear, and click the Clear button.
  • + +

+ +

 

diff --git a/images/appdb_montage.jpg b/images/appdb_montage.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f9cc46a0c6e30e8bf1b6c259ed4f22530a1a5168 GIT binary patch literal 24224 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 NVZo6_h5-x=)&T1GC`bSR literal 0 HcmV?d00001 diff --git a/images/next.gif b/images/next.gif new file mode 100644 index 0000000000000000000000000000000000000000..bbe694e6ed93010eff33cfe525777c56e587e255 GIT binary patch literal 126 zcmZ?wbhEHbRAUflXkY+=|Ns9h{$ycfU|?j>0r5dH3{0Ut{VPwu7Jtl4k%^*7so^ZJW3FjxZsj0-S9 literal 0 HcmV?d00001 diff --git a/images/no_screenshot.gif b/images/no_screenshot.gif new file mode 100644 index 0000000000000000000000000000000000000000..74bdfe3438afff0acfc6719cedc5a5f60d2d54ae GIT binary patch literal 903 zcmZ?wbhEHbY+z_$c+3C-t5&V*?d`R&usC+?*#H0kWn^Ru3kyR-LmxeQ1d>L@Iv_4c zF9XXzffJsq_gcI@yZe8FMqf(iyo^=ra$fH%&^cd{d%t4c`@tfkJ_dj%IPj4i3)gBCA)5 z^b7ZMbcwEBE4F&?LE-s_cdp(eG+%KxXaDA@o7!1U3a@8ny1MG@jCS_+`s=5sp51fr z(&8tx@3OMI5MDT`o?-S1g|CduC$P11US|`0T zI_rsVy5Q~Kwre-;sy#DTcN)*3>xPS2e+%rXTF{>zb+111{MEbuTW2<@MOxsS^{+>;YjI~?d-aNm5|Ns9CZ2vSKG_Z6DdQ_O;;?M`+l zqsT>yJ^21^R8Bj`dvb};6xr)s7EEuAg;n(9EF#O7Qtq;bOzW zGC?Ins5NLwCexJ{cM^>Mep_mrQhR82jJv^cPshtXK~otTb5c`MIAtC@E$(?$$(i6e z=aIksF5hwveO;rF19Li4OU}-f^n83LbLC5Om+sHHhm%&NNv>MzH)qMRbKZwN4@9@R zU75tw@hVZ>v66X1IHz`{Wa<1$m8g|LEqm>|#N!$-xM{!LawRPL?baJ literal 0 HcmV?d00001 diff --git a/images/remove.gif b/images/remove.gif new file mode 100644 index 0000000000000000000000000000000000000000..13a3066d3827f1389c14631c9b358854e45a5456 GIT binary patch literal 144 zcmZ?wbhEHbG-BXoXkY+=|Ns9h{u6aBN=+y^vh*)W*+*mD^E1`cIABS tn^hh2eMFg$wYbMky3wS!+?f4UxNO?eC|B4Hc0>g literal 0 HcmV?d00001 diff --git a/images/s0.gif b/images/s0.gif new file mode 100644 index 0000000000000000000000000000000000000000..21b6be5b730cd0a3015389c4468965a9b33aef71 GIT binary patch literal 59 zcmZ?wbhEHbka~@CXp5)(Fs(RE^)ji#-wLo;qL(xszwQZi>9kPrJ)&M3T BBy<1( literal 0 HcmV?d00001 diff --git a/images/s2.gif b/images/s2.gif new file mode 100644 index 0000000000000000000000000000000000000000..1205878e7cbde573b8c73ba321de02b6550ca1ce GIT binary patch literal 117 zcmZ?wbhEHbOr7n*R-h{wG(TVNm*CJ>|fG14oY@-MV!v0|rq1 z$->CMz|Nopk^!0Fz@qfwMDnFMPi}F#IC?h49C!DUtB^Zr!RlmClW4K@wzbDMK}H5^ E0Pr6r7ytkO literal 0 HcmV?d00001 diff --git a/images/tree.gif b/images/tree.gif new file mode 100644 index 0000000000000000000000000000000000000000..e4e818c3b5b6d3a70976d7fc6e3fc05478b8bef4 GIT binary patch literal 116 zcmZ?wbhEHbRA%61XkY+=|Ns9h{u6aBN=+$XSbdR1;cbM$B1t9<^N QGZ|}z-*@=1aWPl}0BsK{G5`Po literal 0 HcmV?d00001 diff --git a/images/w0.gif b/images/w0.gif new file mode 100644 index 0000000000000000000000000000000000000000..ab1083548c818aaf26473d41804e5469f4219dab GIT binary patch literal 65 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 literal 0 HcmV?d00001 diff --git a/include/.cvsignore b/include/.cvsignore new file mode 100644 index 0000000..55d2fba --- /dev/null +++ b/include/.cvsignore @@ -0,0 +1,2 @@ +stderr + diff --git a/include/appbyvendor_inc.php b/include/appbyvendor_inc.php new file mode 100644 index 0000000..fe0a21b --- /dev/null +++ b/include/appbyvendor_inc.php @@ -0,0 +1,58 @@ + + "; + + foreach($fields as $aField) + { + echo ""; + } + + echo ""; +} + +?> diff --git a/include/appdb.php b/include/appdb.php new file mode 100644 index 0000000..a85ffe0 --- /dev/null +++ b/include/appdb.php @@ -0,0 +1,35 @@ +catHitId"); + } + else + { + mysql_query("INSERT INTO catHitStats VALUES(null, null, '$REMOTE_ADDR', $catId, 1)"); + } +} + +function log_application_visit($appId) +{ + global $REMOTE_ADDR; + + $result = mysql_query("SELECT * FROM appHitStats WHERE ip = '$REMOTE_ADDR' AND appId = $appId"); + if($result && mysql_num_rows($result) == 1) + { + $stats = mysql_fetch_object($result); + mysql_query("UPDATE appHitStats SET count = count + 1 WHERE appHitId = $stats->appHitId"); + } + else + { + mysql_query("INSERT INTO appHitStats VALUES(null, null, '$REMOTE_ADDR', $appId, 1)"); + } +} + +?> diff --git a/include/application.php b/include/application.php new file mode 100644 index 0000000..087a9a3 --- /dev/null +++ b/include/application.php @@ -0,0 +1,78 @@ +data = mysql_fetch_object($result); + } + + + function getAppVersionList() + { + $list = array(); + + $result = mysql_query("SELECT * FROM appVersion ". + "WHERE appId = ". $this->data->appId . " " . + "ORDER BY versionName"); + if(!$result) + return $list; + + while($row = mysql_fetch_object($result)) + { + if($row->versionName == "NONAME") + continue; + $list[] = $row; + } + + return $list; + } + + function getAppVersion($versionId) + { + $result = mysql_query("SELECT * FROM appVersion ". + "WHERE appId = ". $this->data->appId ." AND ". + "versionId = $versionId"); + if(!$result || mysql_num_rows($result) != 1) + return 0; + + return mysql_fetch_object($result); + } + + function getVendor() + { + $result = mysql_query("SELECT * FROM vendor ". + "WHERE vendorId = ". $this->data->vendorId); + if(!$result || mysql_num_rows($result) != 1) + return array("vendorName" => "Unknown"); + + $vendor = mysql_fetch_object($result); + return $vendor; + } + + function getComments($versionId = 0) + { + $list = array(); + + $result = mysql_query("SELECT * FROM appComments ". + "WHERE appId = ". $this->data->appId . " AND " . + "versionId = $versionId " . + "ORDER BY time"); + if(!$result) + return $list; + + while($row = mysql_fetch_object($result)) + $list[] = $row; + + return $list; + } +} diff --git a/include/appversion_inc.php b/include/appversion_inc.php new file mode 100644 index 0000000..6591fa6 --- /dev/null +++ b/include/appversion_inc.php @@ -0,0 +1,61 @@ + + "; + + foreach($fields as $aField) + { + echo ""; + } + + echo ""; +} + +?> diff --git a/include/banner.php b/include/banner.php new file mode 100644 index 0000000..044ed5b --- /dev/null +++ b/include/banner.php @@ -0,0 +1,55 @@ + + * last modified: 2001.10.08 + * + */ + +/* + * Path for Banner Ads + */ + +function banner_display () +{ + // import banner paths from config + global $apidb_root; + $banner_path_468x60 = $apidb_root."banner/468x60/"; + $banner_path_xml = $apidb_root."banner/xml/"; + + // opening html + $banner = ""; + $banner .= "\n\n".''."\n"; + $banner .= '
'."\n"; + + // read dir and get list of banners + $ads = array(); + $d = opendir($banner_path_468x60); + while($entry = readdir($d)) + { + if(!ereg("(.+)\\.gif$", $entry, $arr)) + continue; //" + array_push($ads, $arr[1]); + } + closedir($d); + + // randomly select a banner and display it + $img = $ads[(rand(1,count($ads))-1)]; + $url = get_xml_tag($banner_path_xml.$img.'.xml','url'); + $alt = get_xml_tag($banner_path_xml.$img.'.xml','alt'); + + // da banner + $banner .= ''; + $banner .= ''.$alt.''; + $banner .= ''."\n"; + + // closing html + $banner .= '
'."\n"; + $banner .= ''."\n\n"; + + return $banner; + +} + +?> diff --git a/include/category.php b/include/category.php new file mode 100644 index 0000000..eae9471 --- /dev/null +++ b/include/category.php @@ -0,0 +1,208 @@ +load($id); + } + + + /* + * load the category data into this class + */ + function load($id) + { + $this->id = $id; + + if($id == 0) + { + $this->name = "ROOT"; + } + else + { + $result = mysql_query("SELECT * FROM appCategory WHERE catId = $id"); + if(!$result) { + // category not found! + errorpage("Internal Error: Category not found!"); + return; + } + + $ob = mysql_fetch_object($result); + $this->name = $ob->catName; + } + + $result = mysql_query("SELECT catId, catName, catDescription FROM ". + "appCategory WHERE catParent = $this->id " . + "ORDER BY catName"); + if(mysql_num_rows($result) == 0) + return; // no sub categories + + $this->subcat = array(); + while($row = mysql_fetch_object($result)) + { + // Ignore NONAME categories + if($row->catName == "NONAME") + continue; + $this->subcat[$row->catId] = array($row->catName, $row->catDescription); + } + } + + + /* + * resolve the category id by name + */ + function getCategoryId($name) + { + if($name == "ROOT") + return 0; + + $result = mysql_query("SELECT catId FROM appCategory WHERE ". + "catName = '$name'"); + if(!$result) + return -1; + if(mysql_num_rows($result) != 1) + return -1; + $row = mysql_fetch_object($result); + return $row->catId; + } + + + /* + * returns the list of sub categories + * + * category list has the following format: + * + * { { catId => { catName, catDescription } }, ... } + */ + function getCategoryList() + { + return $this->subcat; + } + + /* + * returns a path like: + * + * { ROOT, Games, Simulation } + */ + function getCategoryPath() + { + $path = array(); + $id = $this->id; + while(1) + { + $result = mysql_query("SELECT catName, catId, catParent FROM appCategory WHERE catId = $id"); + if(!$result || mysql_num_rows($result) != 1) + break; + $cat = mysql_fetch_object($result); + $path[] = array($cat->catId, $cat->catName); + $id = $cat->catParent; + } + $path[] = array(0, "ROOT"); + return array_reverse($path); + } + + + /* + * returns a list of applications in the specified category + */ + function getAppList($id) + { + $result = mysql_query("SELECT appId, appName, description FROM ". + "appFamily WHERE catId = $id ". + "ORDER BY appName"); + if(!$result || mysql_num_rows($result) == 0) + return array(); + + $list = array(); + while($row = mysql_fetch_object($result)) + { + if($row->appName == "NONAME") + continue; + $list[$row->appId] = array($row->appName, $row->description); + } + return $list; + } + + + /* + * returns the number of apps in the specified category + */ + function getAppCount($id, $recurse = 1) + { + $total = 0; + + $result = mysql_query("SELECT appId FROM appFamily WHERE catId = $id"); + if($result) + $total += mysql_num_rows($result); + + if($recurse) + { + $result = mysql_query("SELECT catId FROM appCategory WHERE catParent = $id"); + if($result) + { + while($ob = mysql_fetch_object($result)) + $total += $this->getAppCount($ob->catId, 1); + } + } + return $total; + } +}; + +function appIdToName($appId) +{ + $result = mysql_query("SELECT appName FROM appFamily WHERE appId = $appId"); + if(!$result || !mysql_num_rows($result)) + return ""; // shouldn't normally happen + $ob = mysql_fetch_object($result); + return $ob->appName; +} + +function versionIdToName($versionId) +{ + $result = mysql_query("SELECT versionName FROM appVersion WHERE versionId = $versionId"); + if(!$result || !mysql_num_rows($result)) + return ""; // shouldn't normally happen + $ob = mysql_fetch_object($result); + return $ob->versionName; +} + +// create the Category: line at the top of appdb pages +function make_cat_path($path) +{ + global $appId; + global $versionId; + + $str = ""; + $catCount = 0; + while(list($idx, list($id, $name)) = each($path)) + { + if($name == "ROOT") + $catname = "Main"; + else + $catname = $name; + + if ($catCount > 0) { $str .= " > "; } + $str .= html_ahref($catname,"appbrowse.php?catId=$id"); + $catCount++; + } + + if($appId) + $str .= " > ".html_ahref(appIdToName($appId),"appview.php?appId=$appId"); + + if($versionId) + $str .= " > ".html_ahref(versionIdToName($versionId),"appview.php?appId=$appId&versionId=$versionId"); + + return $str; +} + +?> diff --git a/include/comments.php b/include/comments.php new file mode 100644 index 0000000..48ee412 --- /dev/null +++ b/include/comments.php @@ -0,0 +1,251 @@ +email) + { + $mailto = '' . $ob->username . ''; + } + else + { + $mailto = $ob->username; + } + + echo html_frame_start('','98%'); + echo '',"\n"; + + $ob->subject = stripslashes($ob->subject); + $ob->body = stripslashes($ob->body); + + // message header + echo "
\n"; + echo " $ob->subject
\n"; + echo " by $mailto on $ob->time
\n"; + echo "
\n"; + + // body + echo htmlify_urls($ob->body), "

\n"; + + // only add RE: once + if(eregi("RE:", $ob->subject)) + $subject = $ob->subject; + else + $subject = "RE: $ob->subject"; + + // reply post buttons + echo " [post new] \n"; + echo " [reply to this] \n"; + + echo "
\n"; + echo html_frame_end(); + +} + + +/*========================================================================= + * + * grab comments for appId / versionId + * if parentId is not -1 only comments for that thread are returned + */ +function grab_comments($appId, $versionId, $parentId = -1) +{ + $extra = ""; + if($parentId != -1) + $extra = "AND parentId = $parentId "; + + $qstring = "SELECT from_unixtime(unix_timestamp(time), \"%W %M %D %Y, %k:%i\") as time, ". + "commentId, parentId, appId, versionId, username, email, subject, body ". + "FROM appComments, user_list WHERE appComments.userId = user_list.userid ". + $extra . + "AND appId = $appId AND versionId = $versionId ". + "ORDER BY appComments.time ASC"; + + $result = mysql_query($qstring); + + return $result; +} + +/*========================================================================= + * + * grab comments for appId / versionId + * if parentId is not -1 only comments for that thread are returned + */ +function count_comments($appId, $versionId) +{ + + $qstring = "SELECT count(commentId) as hits FROM appComments WHERE appId = $appId AND versionId = $versionId"; + $result = mysql_query($qstring); + $ob = mysql_fetch_object($result); + return $ob->hits; +} + +/*========================================================================= + * + * display nested comments + * + * handle is a db result set + * + */ +function do_display_comments_nested($handle) +{ + while($ob = mysql_fetch_object($handle)) + { + view_app_comment($ob); + $result = grab_comments($ob->appId, $ob->versionId, $ob->commentId); + if($result && mysql_num_rows($result)) + { + echo "
\n"; + do_display_comments_nested($result); + echo "
\n"; + } + } +} + +function display_comments_nested($appId, $versionId, $threadId) +{ + $result = grab_comments($appId, $versionId, $threadId); + + do_display_comments_nested($result); +} + + +/*========================================================================= + * + * display threaded comments + * + * handle is a db result set + * + */ +function do_display_comments_threaded($handle, $is_main) +{ + if(!$is_main) + echo "
    \n"; + + while($ob = mysql_fetch_object($handle)) + { + if($is_main) + view_app_comment($ob); + else + echo "
  • ". + " $ob->subject by $ob->username on $ob->time
  • \n"; + $result = grab_comments($ob->appId, $ob->versionId, $ob->commentId); + if($result && mysql_num_rows($result)) + { + echo "
    \n"; + do_display_comments_threaded($result, 0); + echo "
    \n"; + } + } + if(!$is_main) + echo "
\n"; +} + +function display_comments_threaded($appId, $versionId, $threadId = 0) +{ + $result = grab_comments($appId, $versionId, $threadId); + + do_display_comments_threaded($result, 1); +} + + +/*========================================================================= + * + * display flat comments + * + */ +function display_comments_flat($appId, $versionId) +{ + $result = grab_comments($appId, $versionId); + + while($ob = mysql_fetch_object($result)) + { + view_app_comment($ob); + } +} + + +function view_app_comments($appId, $versionId, $threadId = 0) +{ + opendb(); + + global $current; + global $cmode; + + + $result = mysql_query("SELECT commentId FROM appComments WHERE appId = $appId AND versionId = $versionId"); + $messageCount = mysql_num_rows($result); + + + //start comment format table + echo html_frame_start("","98%",'',0); + echo '',"\n"; + + echo '',"\n"; + echo '
',"\n"; + + // message display mode changer + if (loggedin()) + { + //FIXME we need to change this so not logged in users can change current view as well + if ($cmode) + $current->setpref("comments:mode", $cmode); + + $sel[$current->getpref("comments:mode")] = 'selected'; + echo '',"\n"; + } + + // blank space + echo '',"\n"; + + // post new message button + echo '',"\n"; + + //end comment format table + echo '
',"\n"; + echo "Application Comments $messageCount total comments "; + echo 'Mode ',"\n"; + echo '
 
',"\n"; + echo '
',"\n"; + echo html_frame_end("The following comments are owned by whoever posted them. CodeWeavers is not responsible for what they say."); + + //start comments + echo '
',"\n"; + + //hide or display depending on pref + if (loggedin()) + $mode = $current->getpref("comments:mode"); + else + $mode = "flat"; + + switch ($mode) + { + case "flat": + display_comments_flat($appId, $versionId); + break; + case "nested": + display_comments_nested($appId, $versionId, $threadId); + break; + case "threaded": + display_comments_threaded($appId, $versionId, $threadId); + break; + } + + echo '
',"\n"; + +} + + +?> diff --git a/include/config.php b/include/config.php new file mode 100644 index 0000000..fe30761 --- /dev/null +++ b/include/config.php @@ -0,0 +1,27 @@ + diff --git a/include/db.php b/include/db.php new file mode 100644 index 0000000..a708c37 --- /dev/null +++ b/include/db.php @@ -0,0 +1,35 @@ + diff --git a/include/footer.php b/include/footer.php new file mode 100644 index 0000000..6627b08 --- /dev/null +++ b/include/footer.php @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/include/form_edit.php b/include/form_edit.php new file mode 100644 index 0000000..b5bb103 --- /dev/null +++ b/include/form_edit.php @@ -0,0 +1,41 @@ + + + + + +   User Name + + + +   Password + + + +   Password (again) + + + +   Real Name + + + +   Email Address + + + +   + + + + + diff --git a/include/form_login.php b/include/form_login.php new file mode 100644 index 0000000..8a9e5cd --- /dev/null +++ b/include/form_login.php @@ -0,0 +1,61 @@ +',"\n"; +echo html_frame_start("Login to Application DB","400","",0) + +?> + + + + + + + + + + + + + + + + + +
User Name
Password
+ +
+ + + +',"\n"; +echo '',"\n"; +echo '',"\n"; + +?> + +

Don't have an account yet?
+ [Create a New Account]

+ +

Lost your password?
+ [Email a New Password]

+ + diff --git a/include/form_new.php b/include/form_new.php new file mode 100644 index 0000000..2a1bbe7 --- /dev/null +++ b/include/form_new.php @@ -0,0 +1,53 @@ +',"\n"; +echo html_frame_start("Create New Application DB Account","400","",0) + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + +
User Name
Password
Password (again)
Real Name
Email Address
+ +
+ + +',"\n"; +echo '',"\n"; + +echo p(),p(),p(); + +?> diff --git a/include/header.php b/include/header.php new file mode 100644 index 0000000..9e02439 --- /dev/null +++ b/include/header.php @@ -0,0 +1,51 @@ + + + + + + + + Wine Application DB <?=$title?> + + + + + + + + + + + + + +
+ + + + + + + +
Wine HQ + + + + + +
+ +
+ +
+
+ diff --git a/include/html.php b/include/html.php new file mode 100644 index 0000000..3a49f72 --- /dev/null +++ b/include/html.php @@ -0,0 +1,351 @@ + 0) + $str = str_repeat(" ", $_indent_level) . $str; + + if($v > 0) + $_indent_level += $v; + + return $str . "\n"; +} + +function do_html_tr($t, $arr, $class, $extra) +{ + if(strlen($class)) + $class = " class=\"$class\""; + + $str = do_indent("", 1); + for($i = 0; $i < sizeof($arr); $i++) + { + if(is_array($arr[$i])) + { + $val = $arr[$i][0]; + $extra = " ".$arr[$i][1]; + } + else + { + $val = $arr[$i]; + $extra = ""; + } + + if (! $val) + { + $val = " "; + } + + if(stristr($val, "<$t")) + { + $str .= do_indent($val); + } + else + { + $str .= do_indent("<$t$class$extra> ".trim($val)." ", 0); + } + } + $str .= do_indent("", -1); + + return $str; +} + +// HTML TH +function html_th($arr, $class = "", $extra = "") +{ + return do_html_tr("th", $arr, $class, $extra); +} + +// HTML TR +function html_tr($arr, $class = "", $extra = "") +{ + return do_html_tr("td", $arr, $class, $extra); +} + +// HTML TABLE +function html_table_begin($extra = "") +{ + return do_indent("", 1); +} + +function html_table_end() +{ + return do_indent("
", -1); +} + + +// HTML HTML +function html_begin() +{ + return do_indent("", 1); +} + +function html_end() +{ + return do_indent("", -1); +} + + +// HTML HEAD +function html_head($title, $stylesheet = 0) +{ + $str = do_indent("", 1); + $str .= do_indent(" $title ", 0); + if($stylesheet) + $str .= do_indent("", 0); + $str .= do_indent("", -1); + + return $str; +} + + +// HTML BODY +function html_body_begin() +{ + return do_indent("", 1); +} + +function html_body_end() +{ + return do_indent("", -1); +} + + +// HTML BR +function html_br($count = 1) +{ + return do_indent(str_repeat("
", $count)); +} + +// HTML A HREF +function html_ahref($label, $url, $extra = "") +{ + $label = stripslashes($label); + if (!$label and $url) + { + return do_indent(" $url "); + } + else if (!$label) + { + return do_indent("   "); + } + else + { + return do_indent(" $label "); + } +} + +// HTML echo a string +function html_echo($str) +{ + return do_indent($str); +} + +// HTML B (bold) +function html_b($str) +{ + return do_indent("$str"); +} + +// HTML SMALL (small text) +function html_small($str) +{ + return do_indent("$str"); +} + +// HTML P +function html_p() +{ + return do_indent("

"); +} + +function html_line($thickness = 1, $colspan = 1, $color = "#000000") +{ + return do_indent(" ". + " "); +} + + + +function html_imagebutton($text, $url, $extra = "") +{ + static $i = 1; + + $i++; + $img1 = apidb_url("util/button.php?text=".urlencode($text)."&pressed=0"); + $img2 = apidb_url("util/button.php?text=".urlencode($text)."&pressed=1"); + + $java = "onMouseDown = 'document.img$i.src = \"$img2\"; return true;' "; + $java .= "onMouseUp = 'document.img$i.src = \"$img1\"; return true;' "; + + return "\n\n $text \n"; +} + + +function html_frame_start($title = "", $width = "", $extra = "", $innerPad = 5) +{ + + global $apidb_root; + + if ($width) { $width = 'width="'.$width.'"'; } + +$str .= ''."\n"; + +if ($title) +{ +$str .= ' + +'; +} + +$str .= ' + + + + + +
+ +
+ + + + + + + + + + + + + + + + +
'.$title.'
+
- + +
+
+'; + + return $str; +} + +function html_frame_end($text = "") +{ + global $apidb_root; + +$str = ' +
+
-
+
+'; + + return $str; +} + + +function html_select($name, $values, $default = null, $descs = null) +{ + $str = "\n"; + + return $str; +} + +function html_back_link($howmany = 1, $url = "") +{ + if (!$url) + { + $url = 'javascript:history.back('.$howmany.');'; + } + return '

   << Back

'."\n"; +} + + +function p() +{ + return "\n

 

\n"; +} + +function add_br($text = "") +{ + $text = ereg_replace("\n","
\n",$text); + return $text; +} + +function make_dll_option_list($varname, $dllid = -1) +{ + $db = new ApiDB(); + + echo "\n"; +} + + +function make_inx_option_list($varname, $inx = null) +{ + $list = array("yes", "no", "stub", "unknown"); + echo "\n"; + +} + + +function make_quality_option_list($varname, $quality) +{ + $list = array(-1, 1, 2, 3, 4, 5); + echo "\n"; +} + +?> diff --git a/include/incl.php b/include/incl.php new file mode 100644 index 0000000..3632475 --- /dev/null +++ b/include/incl.php @@ -0,0 +1,241 @@ +username; + + // Set Page Title + $page_title = $title; + if ($title) + $title = " - $title"; + + // banner ad + include(BASE."include/"."banner.php"); + $banner_ad = banner_display(); + + // Display Header + include(BASE."include/"."header.php"); + + // Display Sidebar + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + + // Display Footer + if(!$header_disabled) + include(BASE."include/"."footer.php"); +} + +/* + * output the sidebar, calls all functions registered with apidb_sidebar_add + */ +function apidb_sidebar() +{ + global $apidb_root; + global $sidebar_func_list; + + //TURN on GLOBAL ADMIN MENU + if (havepriv("admin")) + { + include(BASE."include/"."sidebar_admin.php"); + apidb_sidebar_add("global_admin_menu"); + } + + // Login Menu + include(BASE."include/"."sidebar_login.php"); + apidb_sidebar_add("global_sidebar_login"); + + // Main Menu + include(BASE."include/"."sidebar.php"); + apidb_sidebar_add("global_sidebar_menu"); + + //LOOP and display menus + for($i = 0; $i < sizeof($sidebar_func_list); $i++) + { + $func = $sidebar_func_list[$i]; + $func(); + } +} + + +/* register a sidebar menu function + * the supplied function is called when the sidebar is built + */ +function apidb_sidebar_add($funcname) +{ + global $sidebar_func_list; + array_unshift($sidebar_func_list, $funcname); +} + + +function apidb_image($name) +{ + global $apidb_root; + return $apidb_root."images/$name"; +} + + +/* + * display an error page + */ +function errorpage($text = null, $message = null) +{ + if (!$text) { + $text = "You must be logged in to perform that operation."; + } + apidb_header("Oops"); + echo "
$text
\n"; + echo "

$message

\n"; + apidb_footer(); +} + + + +/* + * redirect to $url + */ +function redirect($url) +{ + header("Location: ".$url); +} + +/* + * redirect back to referer, or else to the main page + */ +function redirectref($url = null) +{ + global $HTTP_REFERER; + + if(!$url) + $url = $HTTP_REFERER; + if(!$url) + $url = apidb_fullurl(); + redirect($url); +} + + +/* + * msgs will be displayed on the Next page view of the same user + */ +function addmsg($text, $color = "black") +{ + global $current; + global $PHPSESSID; + + if($color) + $text = " $text \n"; + + $text = str_replace("'", "\\'", $text); + mysql_query("INSERT INTO sessionMessages VALUES (null, null, '$PHPSESSID', '$text')"); + echo mysql_error(); +} + + + +/* + * output msg_buffer and clear it. + */ +function dumpmsgbuffer() +{ + global $current; + global $PHPSESSID; + + $result = mysql_query("SELECT * FROM sessionMessages WHERE sessionId = '$PHPSESSID'"); + if(!$result) + return; + + while($r = mysql_fetch_object($result)) + { + echo html_frame_start("","300","",5); + echo "
$r->message
"; + echo html_frame_end(" "); + echo "
\n"; + } + + mysql_query("DELETE FROM sessionMessages WHERE sessionId = '$PHPSESSID'"); +} + +?> diff --git a/include/menu.php b/include/menu.php new file mode 100644 index 0000000..de5e392 --- /dev/null +++ b/include/menu.php @@ -0,0 +1,77 @@ +\n"; + +echo ' +
+
\n"; + apidb_sidebar(); + echo "\n"; + + echo html_frame_start($page_title, '98%'); + + // Display Status Messages + dumpmsgbuffer(); +} + + +/* + * output the common apidb footer + */ +function apidb_footer() +{ + global $apidb_root; + global $current; + + echo html_frame_end(); + + //Close Sidebar and Content Well + echo "
+ + + + + + + +
+ + + + + + + + + + + + +
  '.$name.'
+
+ + +
+ +'; + + } + + /* add a table row */ + function add($name, $url = null) + { + if($url) + { + echo " \n"; + } else { + echo " \n"; + } + } + + function addmisc($stuff, $align = "left") + { + echo " \n"; + } + + function done($form = null) + { + global $apidb_root; + +echo ' +
 $name
 $name
 $stuff
+
+
-
+ +
+'; + + if ($form) + echo "\n"; + + } +} +?> diff --git a/include/parsedate.php b/include/parsedate.php new file mode 100644 index 0000000..dfa8326 --- /dev/null +++ b/include/parsedate.php @@ -0,0 +1,81 @@ + 1, "feb" => 2, "mar" => 3, "apr" => 4, "may" => 5, "jun" => 6, + "jul" => 7, "aug" => 8, "sep" => 9, "oct" => 10, "nov" => 11, "dec" => 12); + $ampm = array("am" => 00, "pm" => 12); + + if(!$datestr) + return -1; + + $datestr = strtolower($datestr); + $datestr = ereg_replace("[,]", "", $datestr); + $dp = explode(' ', $datestr); + while(list($idx, $part) = each($dp)) + { + //echo "PART($part)
"; + + /* 23:59:59 */ + if(ereg("^([0-9]+):([0-9]+):([0-9]+)$", $part, $arr)) + { + $hour = $arr[1]; + $minute = $arr[2]; + $second = $arr[3]; + continue; + } + + /* 23:59 */ + if(ereg("^([0-9]+):([0-9]+)$", $part, $arr)) + { + $hour = $arr[1]; + $minute = $arr[2]; + $second = 0; + continue; + } + + /* 2000-12-31 (mysql date format) */ + if(ereg("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$", $part, $arr)) + { + $year = $arr[1]; + $month = $arr[2]; + $day = $arr[3]; + continue; + } + + if(defined($ampm[$part])) + { + $hour += $ampm[$part]; + continue; + } + if($monthnames[substr($part, 0, 3)]) + { + $month = $monthnames[substr($part, 0, 3)]; + continue; + } + + if($part > 1900) + { + $year = $part; + continue; + } + if($part > 31) + { + $year = 1900 + $part; + continue; + } + if($part >= 1 && $part <= 31) + { + $day = $part; + continue; + } + + //echo "Unparsed: '$part'
\n"; + + } + + return mktime($hour, $minute, $second, $month, $day, $year); +} + +?> diff --git a/include/pn_buttons.php b/include/pn_buttons.php new file mode 100644 index 0000000..716c093 --- /dev/null +++ b/include/pn_buttons.php @@ -0,0 +1,76 @@ + 0) + { + $vars["curPos"] = $curPos - $linesPerPage; + $prev_url = "stdquery.php?".build_urlarg($vars); + } + + if($endpos < $totalCount) + { + $vars["curPos"] = $curPos + $linesPerPage; + $next_url = "stdquery.php?".build_urlarg($vars); + } + + // show prev button if nessessary + if($prev_url) + { + echo html_b(html_ahref("<< Prev", $prev_url)); + } + + // show numbered links + if(!$useNextOnly && $endpos <= $totalCount) + { + while($buttonCount <= $numButtons + 1) + { + if($curPage == ($buttonCount - 1)) + { + echo html_b("$buttonCount"); + } + else + { + $vars["curPos"] = ($buttonCount - 1) * $linesPerPage; + $url = "stdquery.php?".build_urlarg($vars); + echo " ".html_ahref("$buttonCount", $url)." "; + } + + if(!($buttonCount % 40)) + { + echo html_p(); + } + $buttonCount++; + } + + } + + // show next button if nessessary + if($next_url) + { + echo html_b(html_ahref("Next >>", $next_url)); + } + + echo "
".html_small("listing $numRows record".($numRows == 1 ? "" : "s")." ".($curPos+1)." to $endpos of $totalCount total"); +} + +?> diff --git a/include/qclass.php b/include/qclass.php new file mode 100644 index 0000000..79fffd0 --- /dev/null +++ b/include/qclass.php @@ -0,0 +1,246 @@ + "apiid", + "apimslinks" => "apiid", + "dlldefinition" => "dllid", + "implementation" => "apiid", + "user_list" => "userid", + "project_list" => "id", + "appFamily" => "appId", + "appVersion" => "versionId", + ); + + + + + function qclass() + { + $this->clear(); + } + + + function clear() + { + $this->fields = array(); + $this->tables = array(); + $this->where = array(); + $this->limit = 10; + $this->order = ""; + } + + + /* + * resolve used tables from fields + */ + function resolve_tables($fields) + { + $tables = array(); + while(list($idx, $field) = each($fields)) + { + //echo "Field: $field
\n"; + if(!ereg("^(.+)\\.(.+)$", $field, $arr)) + continue; + $tables[$arr[1]] = $arr[1]; + } + return values($tables); + } + + + + function get_id($table) + { + $id = $this->table_ids[$table]; + if($id) + return $id; + if(ereg("^impl_.*$", $table)) + return "apiid"; + return null; + } + + function get_rel($table1, $table2) + { + $id1 = $this->get_id($table1); + $id2 = $this->get_id($table2); + + if($id1 == "dllid" && $table2 == "apimsdefinition") + return $id1; + if($id2 == "dllid" && $table1 == "apimsdefinition") + return $id2; + + if($id1 == $id2) + return $id1; + + return null; + } + + function resolve_where($tables) + { + $tables = values($tables); + $arr = array(); + $have = array(); + while(list($idx, $table) = each($tables)) + { + for($i = 0; $i < sizeof($tables); $i++) + { + //echo "Checking $table - $tables[$i]
\n"; + if($table == $tables[$i]) + continue; + $id = $this->get_rel($table, $tables[$i]); + if(!$id) + continue; + if($have[$id][$table]) + continue; + $have[$id][$table] = 1; + $have[$id][$tables[$i]] = 1; + $arr[] = "$table.$id = $tables[$i].$id"; + } + } + + /* + apidb_header(); + echo "RESULT: ".implode(" AND ", $arr); + apidb_footer(); + exit; + */ + return $arr; + } + + + + function process($vars) + { + extract($vars); + //var_dump($vars); + + $sfields = $fields; + + if(!$implementations) + $implementations = array("wine"); //FIXME + + while(list($idx, $impl) = each($implementations)) + { + + // Check for quality? + if($quality[$idx] && $quality[$idx] != "ALL") + { + if($quality[$idx] == "UNKNOWN") + $this->where[] = "impl_$impl.quality IS NULL"; + else + $this->where[] = "impl_$impl.quality >= $quality[$idx]"; + $sfields[] = "impl_$impl.quality"; + } + + // Check for presence? + if($presence[$idx] && $presence[$idx] != "ALL") + { + $this->where[] = "impl_$impl.presence = '$presence[$idx]'"; + $sfields[] = "impl_$impl.presence"; + } + + // Check last modified? + if($lastmod[$idx] > 0) + { + $time = time() - ($lastmod[$idx] * 24 * 3600); + $this->where[] = "impl_$impl.lastmod > from_unixtime($time)"; + $sfields[] = "impl_$impl.lastmod"; + } + + } + + // Search in a specific DLL? + if($dllid && $dllid != "ALL") + $this->where[] = "dlldefinition.dllid = $dllid"; + + // Check for rating? (APPDB) + if($rating && $rating != "ANY") + { + + $q = ""; + if($system == "ANY" || $system == "windows") + { + $q .= " appVersion.rating_windows >= $rating "; + $sfields[] = "appVersion.rating_windows"; + } + if($system == "ANY" || $system == "fake") + { + if($system == "ANY") + $q .= " OR "; + $q .= " appVersion.rating_fake >= $rating "; + $sfields[] = "appVersion.rating_fake"; + } + $this->where[] = "appVersion.appId = appFamily.appId AND ($q)"; + } + + // Are we searching? + if($searchfor) + { + if(ereg("^[0-9]+$", $searchfor)) + // exact match if we're searching for a number + $this->where[] = "$searchwhat = $searchfor"; + else + // patterns are case insensitive in MySQL + $this->where[] = "$searchwhat LIKE '%$searchfor%'"; + } + + // Must we join? + if($join) + { + $this->where[] = $join; + } + + $this->fields = $fields; + $this->tables = $this->resolve_tables($sfields); + $this->where = array_merge($this->resolve_where($this->tables), $this->where); + + } + + function add_where($str) + { + $this->where[] = $str; + } + + function add_field($field) + { + $this->fields[] = $field; + } + + function add_fields($arr) + { + $this->fields = array_merge($this->fields, $arr); + } + + function resolve() + { + $this->tables = $this->resolve_tables($this->fields); + $this->where = array_merge($this->resolve_where($this->tables), $this->where); + } + + + function get_query() + { + $query = array(); + $query[] = "SELECT"; + $query[] = implode(", ", $this->fields); + $query[] = "FROM"; + $query[] = implode(", ", $this->tables); + if(sizeof($this->where)) + { + $query[] = "WHERE"; + $query[] = implode(" AND ", $this->where); + } + // add LIMIT etc. + + return implode(" ", $query); + } +} diff --git a/include/query_appbyvendor.php b/include/query_appbyvendor.php new file mode 100644 index 0000000..51c5476 --- /dev/null +++ b/include/query_appbyvendor.php @@ -0,0 +1,37 @@ + + + + + + + + +
Search Apps by Vendor +
+
+ Vendor Name: + (leave blank to match all) + +

+ Verbose query results
+ Edit mode
\n"; ?> + +
Entries Per Page: + +
+
+
+ + diff --git a/include/query_apps.php b/include/query_apps.php new file mode 100644 index 0000000..9b04132 --- /dev/null +++ b/include/query_apps.php @@ -0,0 +1,53 @@ + + + + + + + + + +
Search Apps +
+
+ + App Name: + (leave blank to match all) + + + + +

+ Verbose query results
+ Edit mode
\n"; ?> + +
Rating + or higher + + + +
Entries Per Page: + +
+
+
+ + diff --git a/include/query_inc.php b/include/query_inc.php new file mode 100644 index 0000000..09d16ca --- /dev/null +++ b/include/query_inc.php @@ -0,0 +1,189 @@ +"; + + // Only permit sql SELECT statements + if(!eregi("^select .*$", $query)) + { + echo " Invalid SQL Query "; + echo "
$query
"; + return; + } + + opendb(); + + $tmpq = str_replace("\\", "", $query); + + $endPos=$curPos+$linesPerPage; + $tcurpos = $curPos+$startapi; + $tendpos = $endPos+$startapi; + + // set a limit if not already set + if(!stristr($query, "limit")) + $tmpq .= " LIMIT $tcurpos,$linesPerPage"; + + // execute the db query + $tstamp = time(); + $result = mysql_query($tmpq); + $tstamp = time() - $tstamp; + + if(debugging()) + echo " QUERY TIME: $tstamp seconds
\n"; + + // query error! + if(!$result) + { + echo "$query

\n"; + echo "A QUERY error occurred: ".mysql_error()."\n"; + exit; + } + + $numRows = mysql_num_rows($result); + $numCols = mysql_num_fields($result); + + $curPage = $curPos/$linesPerPage; + $tmendpos = $curPos + $numRows; + $explain = "stdquery.php?query=".urlencode("EXPLAIN $tmpq"); + + + echo html_br(2); + + // set $debug to enable query debugging + if($debug || stristr($tmpq, "explain")) + { + $str = eregi_replace("(SELECT|EXPLAIN|DISTINCT|FROM|WHERE|AND". + "|OR |IS NULL|IS NOT NULL|LIMIT|ORDER BY". + "|GROUP BY)", + "
\\1
", $tmpq); + echo "
$str
\n"; + } + + echo html_echo("
"); + + add_pn_buttons($vars, $tmendpos); + echo html_br(2); + + // output table header + echo html_table_begin("width='80%' cellspacing=1 border=0 rules=rows frame=hsides"); + $helems = array(); + for($k = 0; $k < $numCols; $k++) + { + $name = mysql_field_name($result, $k); + $helems[] = $name; + if($name == "apiid") + $have_apiid = 1; + } + echo html_th($helems, "title"); + + $curapiid=0; + $curName="[NONAME]"; + + for($i = 0; $i < $numRows; $i++) + { + $row = mysql_fetch_array($result, MYSQL_BOTH); + $color = ($i % 2); + $arr = array(); + + for($k = 0; $k < $numCols; $k++) + { + $fname = mysql_field_name($result, $k); + + + if($fname == "username") + { + $username = $row[$k]; + $userid = $row["userid"]; + $arr[] = html_ahref($username." ", apidb_url("edituser.php?userid=$userid&username=$username")); + continue; + } + + if($fname == "vendorName") + { + initFields(); + $url = "vendorview.php?vendorId=".$row["vendorId"]; + $arr[] = html_ahref($row[$k], $url); + continue; + } + + if($fname == "appName") + { + initFields(); + $url = "appview.php?appId=".$row["appId"]; + $arr[] = html_ahref($row[$k], $url); + continue; + + } + + if($fname == "versionName") + { + $versionId = $row["versionId"]; + $url = "admin/editAppVersion.php?versionId=$versionId"; + $arr[] = html_ahref($row[$k], $url); + continue; + } + + if($fname == "webPage") + { + + $url = $row[$k]; + $theLink = "$url"; + $arr[] = html_ahref($url, $theLink); + + continue; + } + + if(mysql_field_type($result, $k) == "int") + { + $val = (int)$row[$k]; + $arr[] = "
$val
"; + } + else + { + if(!$row[$k]) + $arr[] = " "; + else + $arr[] = "$row[$k]"; + } + } + + echo html_tr($arr, "color$color"); + } + + echo html_table_end(); + echo html_br(); + + add_pn_buttons($vars, $tmendpos); + echo html_echo("
"); + + mysql_free_result($result); + closedb(); +} + + +?> + diff --git a/include/query_users.php b/include/query_users.php new file mode 100644 index 0000000..b5c9259 --- /dev/null +++ b/include/query_users.php @@ -0,0 +1,59 @@ + + + + +
+ + + + + + + + + + + + + + + + + +
Pattern
(leave blank to match all)
Entries Per Page + +
+ + + + + + + + +
+ + + + diff --git a/include/query_vendors.php b/include/query_vendors.php new file mode 100644 index 0000000..0b2de0b --- /dev/null +++ b/include/query_vendors.php @@ -0,0 +1,37 @@ + + + + + + + + + +
Search Vendors +
+
+ + Pattern: + (leave blank to match all) + + + + +

+ Verbose query results
+ Edit mode
\n"; ?> + +
Entries Per Page: + +
+
+
+ + diff --git a/include/rating.php b/include/rating.php new file mode 100644 index 0000000..6622ce5 --- /dev/null +++ b/include/rating.php @@ -0,0 +1,210 @@ +userid; + + $result = mysql_query("SELECT score FROM appRating WHERE versionId = $versionId AND system = '$system' AND userId = $userId"); + if(!$result) + return 0; + $ob = mysql_fetch_object($result); + return $ob->score; +} + + + +/*========================================================================= + * + * Display the app(-version) rating menu + * + */ +function rating_menu() +{ + global $versionId; + global $apidb_root; + + $s = 's1'; + $n = 's0'; + + $j = new htmlmenu("Compatibility Rating","updaterating.php"); + + $r_win = rating_current_for_user($versionId, "windows"); + $r_fake = rating_current_for_user($versionId, "fake"); + + $wchk = array('checked',' ',' ',' ',' ',' '); + $fchk = array('checked',' ',' ',' ',' ',' '); + + if($r_win) + { + $wchk[0] = ' '; + $wchk[$r_win] = 'checked'; + } + + if($r_fake) + { + $fchk[0] = ' '; + $fchk[$r_fake] = 'checked'; + } + + $j->addmisc("". + "". + "". + "
With Windows With WindowsWithout Windows Without Windows
"); + + $j->addmisc("".$n.$n.$n.$n.$n."","center"); + $j->addmisc("".$s.$n.$n.$n.$n."","center"); + $j->addmisc("".$s.$s.$n.$n.$n."","center"); + $j->addmisc("".$s.$s.$s.$n.$n."","center"); + $j->addmisc("".$s.$s.$s.$s.$n."","center"); + $j->addmisc("".$s.$s.$s.$s.$s."","center"); + + + $j->addmisc("","center"); + $j->addmisc(""); + + $j->add("Rating Help", $apidb_root."help/?topic=ratings"); + + $j->done(1); +} + + +/*========================================================================= + * + * returns the avg rating for versionId + * + */ +function rating_for_version($versionId, $system) +{ + $result = mysql_query("SELECT avg(score) as rating, count(id) as hits FROM appRating ". + "WHERE versionId = $versionId and system = '$system'"); + if(!$result) + return 0; + $ob = mysql_fetch_object($result); + return $ob; +} + + +/*========================================================================= + * + * returns rating as star images + * + */ +function rating_stars_for_version($versionId, $system) +{ + global $apidb_root; + + $r = rating_for_version($versionId, $system); + + $s = 's1'; + $n = 's0'; + $h = 's2'; + + if ($system == "fake") + { + $win_gif = "w0.gif"; + $alt_desc = "Without Windows"; + } + else + { + $win_gif = "w1.gif"; + $alt_desc = "With Windows"; + } + + if(!$r->rating) + { + $str = ""; + for($c = 0; $c < 5; $c++) { $str .= $n; } + $str = "$alt_desc ".$str."
"."unrated".""; + return $str; + } + + $result = ""; + for($i = 0; $i < (int)floor($r->rating); $i++) + $result .= $s; + if(floor($r->rating) < round($r->rating)) + { + $i++; + $result .= $h; + } + for(; $i < 5; $i++) + $result .= $n; + + $result = "$alt_desc ".$result. + "
".substr($r->rating,0,4). + " (".$r->hits." votes) ".""; + + return $result; +} + +/*========================================================================= + * + * called by /updaterating.php to update the rating table + * + */ +function rating_update($vars) +{ + global $current; + + if(!loggedin()) + { + // do something, must be logged in + return; + } + + $userId = $current->userid; + $versionId = $vars["versionId"]; + $score_w = $vars["score_w"]; + $score_f = $vars["score_f"]; + + if($score_w) + { + $result = mysql_query("SELECT * FROM appRating WHERE versionId = $versionId AND ". + "userId = $userId AND system = 'windows'"); + if($result && mysql_num_rows($result)) + { + $ob = mysql_fetch_object($result); + mysql_query("UPDATE appRating SET score = $score_w WHERE id = $ob->id"); + } + else + mysql_query("INSERT INTO appRating VALUES (null, null, $versionId, $userId, 'windows', $score_w)"); + + $r = rating_for_version($versionId, "windows"); + mysql_query("UPDATE appVersion SET rating_windows = $r->rating WHERE versionId = $versionId"); + } + + if($score_f) + { + $result = mysql_query("SELECT * FROM appRating WHERE versionId = $versionId AND ". + "userId = $userId AND system = 'fake'"); + if($result && mysql_num_rows($result)) + { + $ob = mysql_fetch_object($result); + mysql_query("UPDATE appRating SET score = $score_f WHERE id = $ob->id"); + } + else + mysql_query("INSERT INTO appRating VALUES (null, null, $versionId, $userId, 'fake', $score_f)"); + + $r = rating_for_version($versionId, "fake"); + mysql_query("UPDATE appVersion SET rating_fake = $r->rating WHERE versionId = $versionId"); + } +} + +?> diff --git a/include/session.php b/include/session.php new file mode 100644 index 0000000..73b85c7 --- /dev/null +++ b/include/session.php @@ -0,0 +1,113 @@ +connect(); +} + + +function apidb_session_destroy() +{ + session_destroy(); +} + + + +/* + * session handler functions + * sessions are stored in a mysql table + * + */ + +function _session_open($save_path, $session_name) +{ + opendb(); + //mysql_query("CREATE TABLE IF NOT EXISTS session_list (session_id varchar(64) not null, ". + // "userid int, ip varchar(64), data text, messages text, stamp timestamp, primary key(session_id))"); + return true; +} + +function _session_close() +{ + return true; +} + +function _session_read($key) +{ + global $msg_buffer; + + opendb(); + $result = mysql_query("SELECT data, messages FROM session_list WHERE session_id = '$key'"); + + if(!$result) + return null; + $r = mysql_fetch_object($result); + + if($r->messages) + $msg_buffer = explode("|", $r->messages); + + return $r->data; +} + +function _session_write($key, $value) +{ + global $current; + global $msg_buffer; + global $apidb_debug; + + opendb(); + + + if($msg_buffer) + $messages = implode("|", $msg_buffer); + else + $messages = ""; + + + // remove single quotes + $value = str_replace("'", "", $value); + + + //DEBUGGING + if ($apidb_debug) + mysql_query("INSERT INTO debug VALUES(null, '$key = $messages')"); + + + if($current) + mysql_query("REPLACE session_list VALUES ('$key', $current->userid, '".get_remote()."', '$value', '$messages', NOW())"); + else + mysql_query("REPLACE session_list VALUES ('$key', 0, '".get_remote()."', null, '$messages', NOW())"); + + return true; + +} + +function _session_destroy($key) +{ + mysql_query("DELETE FROM session_list WHERE session_id = '$key'"); + return true; +} + +function _session_gc($maxlifetime) +{ + // delete sessions older than 2 days + mysql_query("DELETE FROM session_list WHERE to_days(now()) - to_days(stamp) >= 2"); + return true; +} + +session_set_save_handler("_session_open", + "_session_close", + "_session_read", + "_session_write", + "_session_destroy", + "_session_gc"); + +session_register("current"); + +?> diff --git a/include/sidebar.php b/include/sidebar.php new file mode 100644 index 0000000..28713cc --- /dev/null +++ b/include/sidebar.php @@ -0,0 +1,41 @@ +add("Back to WineHQ", "http://www.winehq.org/"); + $g->done(); + + $g = new htmlmenu("App DB"); + $g->add("AppDB Home", $apidb_root); + $g->add("Browse Apps", $apidb_root."appbrowse.php"); + $g->add("Top 25", $apidb_root."votestats.php"); + $g->add("Submit App", $apidb_root."appsubmit.php"); + $g->add("Documentation", $apidb_root."help/"); + $g->add("Help & Support", $apidb_root."support.php"); + $g->done(); + + $g = new htmlmenu("Search"); + $g->addmisc(app_search_box($q)); + $g->done(); + +} + + +function app_search_box($q = '') +{ + $str .= "
\n"; + $str .= ""; + $str .= "\n"; + $str .= "
\n"; + return $str; +} + +?> diff --git a/include/sidebar_admin.php b/include/sidebar_admin.php new file mode 100644 index 0000000..6915859 --- /dev/null +++ b/include/sidebar_admin.php @@ -0,0 +1,26 @@ +add("Add Category", $apidb_root."admin/addCategory.php"); + $g->add("Add Application", $apidb_root."admin/addAppFamily.php?catId=0"); + $g->add("Add Vendor", $apidb_root."admin/addVendor.php"); + + $g->addmisc(" "); + $g->add("List Users", $apidb_root."admin/"); + $g->add("View App Queue", $apidb_root."admin/adminAppQueue.php"); + + $g->done(); + +} + +?> diff --git a/include/sidebar_login.php b/include/sidebar_login.php new file mode 100644 index 0000000..8193dbe --- /dev/null +++ b/include/sidebar_login.php @@ -0,0 +1,28 @@ +add("Logout", $apidb_root."account.php?cmd=logout"); + $g->add("Preferences", $apidb_root."preferences.php"); + } + else + { + $g->add("Login", $apidb_root."account.php?cmd=login"); + } + + $g->done(); + +} + +?> diff --git a/include/tableve.php b/include/tableve.php new file mode 100644 index 0000000..cb68493 --- /dev/null +++ b/include/tableve.php @@ -0,0 +1,503 @@ +mode = $mode; + $this->titleField = ""; + $this->titleText = ""; + $this->numberedTitles = 0; + + opendb(); + } + + function test($query) + { + $result = mysql_query($query); + $nfields = mysql_num_fields($result); + $nrows = mysql_num_rows($result); + $table = mysql_field_table($result, 0); + + echo "Table: $table
Fields: $nfields
Rows: $nrows

\n"; + + $i = 0; + while($i < $nfields) + { + $type = mysql_field_type($result, $i); + $name = mysql_field_name($result, $i); + $len = mysql_field_len($result, $i); + $flags = mysql_field_flags($result, $i); + + echo "$type | $name | $len | $flags
\n"; + $i++; + } + + } + + /* this is a bit of a hack, + * we first create an empty entry, and then simply use the + * edit() function to do the rest of the work for us. + */ + function create($query, $table, $idcolumn) + { + $result = mysql_query($query); + $id = mysql_insert_id(); + + $new_query = "SELECT * FROM $table WHERE $idcolumn = $id"; + $this->edit($new_query); + } + + + function view($query) + { + //$this->test($query); + + $nrows = 0; + + $result = mysql_query($query); + $nrows = mysql_num_rows($result); + + if(debugging()) + { + echo "Query returns $nrows rows."; + } + + for($i = 0; $i < $nrows; $i++) + { + $this->view_entry($result, $i); + echo "
\n"; + } + } + + function view_entry($result, $num) + { + $nfields = mysql_num_fields($result); + $fields = mysql_fetch_array($result, MYSQL_BOTH); + + $titleValue = $fields[$this->titleField]; + $titleText = $this->titleText; + if($this->numberedTitles) + { + // don't want zero-based. + $num++; + $titleText .= " # $num"; + } + + //echo "\n"; + //echo "\n"; + + //echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c = 0; + while($ob = mysql_fetch_object($result)) + { + //skip if a NONAME + if ($ob->appName == "NONAME") { continue; } + + //set row color + if ($c % 2 == 1) { $bgcolor = '#E0E0E0'; } else { $bgcolor = '#EFEFEF'; } + + //count versions + $query = mysql_query("SELECT count(*) as versions FROM appVersion WHERE appId = $ob->appId AND versionName != 'NONAME'"); + $y = mysql_fetch_object($query); + + //format desc + $desc = substr(stripslashes($ob->description),0,75); + + //display row + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c++; + } + + echo "\n"; + echo "
\n"; + + echo html_frame_start("Viewing $titleValue $titleText","80%","",0); + echo "\n"; + + for($i = 0; $i < $nfields; $i++) + { + $field = mysql_fetch_field($result, $i); + + if(ereg("^impl_(.+)$", $field->table, $arr)) + { + if($cur_impl != $arr[1]) + echo "\n"; + $cur_impl = $arr[1]; + } + + echo ""; + echo "\n"; + } + + echo "
".ucfirst($arr[1])." Implementation
$field->name "; + $this->view_entry_output_field($field, $fields[$i], 0); + echo "
\n"; + echo html_frame_end(); + + } + + + function edit($query) + { + $result = mysql_query($query); + if(!$result) + echo "Oops: ".mysql_error()."
$query
\n"; + $nrows = mysql_num_rows($result); + + echo "
\n"; + + for($i = 0; $i < $nrows; $i++) + { + $this->edit_entry($result); + echo "
\n"; + } + + echo html_frame_start("Update Database",100); + echo "\n"; + echo html_frame_end(); + + echo "
\n"; + } + + + function edit_entry($result) + { + $nfields = mysql_num_fields($result); + $fields = mysql_fetch_array($result); + + echo html_frame_start(ucfirst($this->mode),"80%","",0); + echo "\n"; + + $cur_impl = null; + for($i = 0; $i < $nfields; $i++) + { + global $testvar; + $field = mysql_fetch_field($result, $i); + $len = mysql_field_len($result, $i); + + if(ereg("^impl_(.+)$", $field->table, $arr)) + { + if($cur_impl != $arr[1]) + echo "\n"; + $cur_impl = $arr[1]; + } + + echo ""; + echo "\n"; + } + + echo "
".ucfirst($arr[1])." Implementation
$field->name    "; + $this->edit_entry_output_field($field, $fields[$i], $len); + echo "
\n"; + echo html_frame_end(); + } + + function timestamp_to_unix($stamp) + { + $result = mysql_query("select unix_timestamp($stamp)"); + if(!$result) + return 0; + $r = mysql_fetch_row($result); + return $r[0]; + } + + function make_option_list($varname, $cvalue, $table, $idField, $nameField, $where = "") + { + + $result = mysql_query("SELECT $idField, $nameField FROM $table $where ORDER BY $nameField"); + if(!result) + return; // Oops + + echo "\n"; + } + + + function edit_entry_output_field($field, $value, $len) + { + static $idx = 0; + + $idx++; + if($len > 50) + $len = 50; + + $varname = "FIELD_".$field->table."___".$field->name."[]"; + echo "\n"; + + if($field->name == "appId" && $field->table != "appFamily") + { + $this->make_option_list($varname, $value, "appFamily", "appId", "appName"); + return; + } + + if($field->name == "vendorId" && $field->table != "vendor") + { + $this->make_option_list($varname, $value, "vendor", "vendorId", "vendorName"); + return; + } + + if($field->name == "catId" && $field->table != "appCategory") + { + $this->make_option_list($varname, $value, "appCategory", "catId", "catName"); + return; + } + + if($field->name == "catParent") + { + $this->make_option_list($varname, $value, "appCategory", "catId", "catName"); + return; + } + + if($field->name == "keywords") + { + echo "\n"; + return; + } + + switch($field->type) + { + case "string": + case "enum": + case "int": + case "text": + echo "\n"; + break; + case "blob": + echo "\n"; + break; + case "timestamp": + $time = $this->timestamp_to_unix($value); + echo makedate($time); + break; + case "datetime": + $time = parsedate($value); + echo makedate($time); + break; + default: + echo "$value  \n"; + break; + } + + $this->entry_add_extra($field, $value); + } + + + + function view_entry_output_field($field, $value, $len) + { + if($len > 50) + $len = 50; + + //FIXME: need a better way for special cases + if(!$value && $field->name == "comments") + { + echo "none"; + return; + } + if(!$value && ($field->name == "location" || $field->name == "quality")) + { + echo "unknown"; + return; + } + + if($field->name == "lastmodby") + { + $user = new user(); + $name = $user->lookup_username($value); + if(!$name) + $name = "system"; + echo "$name ($value)"; + return; + } + + + switch($field->type) + { + case "string": + case "enum": + case "int": + case "blob": + echo "$value  \n"; + break; + case "timestamp": + $time = $this->timestamp_to_unix($value); + echo makedate($time); + break; + case "datetime": + $time = parsedate($value); + echo makedate($time); + break; + default: + echo "$value  \n"; + break; + } + + $this->entry_add_extra($field, $value); + } + + + /* + * add extra stuff to certain fields + */ + function entry_add_extra($field, $value) + { + /* + * add extra stuff to certain fields + */ + + if($field->name == "mslink" && $value) + { + echo html_imagebutton("Go!", $value); + } + + if($field->name == "apiname") + { + echo html_imagebutton("Wine LXR", "http://twine.codeweavers.com/lxr/ident?i=$value"); + echo html_imagebutton("Wine API", "http://www.winehq.com/WineAPI/$value.html"); + } + } + + + + /* + * required field for each table. + * When editing a query this field needs to be present in the query + * in order to identify the correct row to update. + */ + var $table_ids = array( + "user_list" => "userid", + "appFamily" => "appId", + "appVersion" => "versionId", + "userExperience" => "uExpId", + "appCategory" => "catId", + "vendor" => "vendorId", + "appNotes" => "noteId" + ); + + function get_id($name) + { + reset($this->table_ids); + while(list($table, $id) = each($this->table_ids)) + { + $r = "^$table$"; + //echo "Checking $r against $name
\n"; + if(ereg($r, $name)) + { + //echo "ID for $name -> $id
\n"; + return $id; + } + } + return null; + } + + /* + * update() expects $HTTP_POST_VARS as argument + * this is where things are getting kinda complex, here we update " + * multiple entries with multiple fields in multiple tables (get it?) + */ + function update($vars) + { + global $current; + + $tables = array(); + $fieldnames = array(); + $num_entries = 0; + + while(list($varname, $arr) = each($vars)) + { + if(!ereg("^FIELD_([a-zA-Z_]+)___(.+)$", $varname, $regs)) + continue; + + $tables[$regs[1]][] = $regs[2]; + $fieldnames[$regs[2]] = $arr; + $num_entries = sizeof($arr); + } + + while(list($table, $fields) = each($tables)) + { + echo " $table (".$this->get_id($table).") "; + + if($fieldnames[$this->get_id($table)]) + echo "OK!"; + + echo "
\n"; + + for($i = 0; $i < sizeof($fields); $i++) + echo "- $fields[$i]
\n"; + + echo "
\n"; + } + + for($i = 0; $i < $num_entries; $i++) + { + reset($tables); + while(list($table, $fields) = each($tables)) + { + $update = "UPDATE $table SET "; + + $count = sizeof($fields); + reset($fields); + while(list($idx, $field) = each($fields)) + { + $count--; + + if($this->table_ids[$table] == $field) + { + continue; + } + $key = "FIELD_".$table."___".$field; + $type = $vars["TYPE_$key"][$i]; + + if($type == "int") + $update .= "$field = ".$vars[$key][$i]; + else + $update .= "$field = '".addslashes($vars[$key][$i])."'"; + + if($count) + $update .= ", "; + } + + $value = $fieldnames[$this->get_id($table)][$i]; + + $update .= " WHERE ".$this->get_id($table)." = $value"; + + if(!mysql_query($update)) + { + $thisError = "

Query:: $update

\n"; + $thisError .= "

".mysql_error()."

"; + addmsg($thisError,"red"); + } + else + { + addmsg("Database Operation Complete!","green"); + } + + if(ereg("^impl_.+$", $table)) + { + $value = $fieldnames["apiid"][$i]; + mysql_query("UPDATE $table SET lastmodby = $current->userid WHERE apiid = $value"); + } + } + } + + + + } + + function set_title_field($newTitleField) + { + $this->titleField = $newTitleField; + } + + function set_title_text($newTitleText) + { + $this->titleText = $newTitleText; + } + + function set_numbered_titles() + { + $this->numberedTitles = 1; + } + +}; + +?> diff --git a/include/user.php b/include/user.php new file mode 100644 index 0000000..9de9a42 --- /dev/null +++ b/include/user.php @@ -0,0 +1,319 @@ +connect(); + } + + + function connect() + { + $this->link = opendb(); + } + + + /* + * check if a user exists + * returns TRUE if the user exists + */ + function exists($username) + { + $result = mysql_query("SELECT * FROM user_list WHERE username = '$username'", $this->link); + if(!$result || mysql_num_rows($result) != 1) + return 0; + return 1; + } + + + function lookup_username($userid) + { + $result = mysql_query("SELECT username FROM user_list WHERE userid = $userid"); + if(!$result || mysql_num_rows($result) != 1) + return null; + $ob = mysql_fetch_object($result); + return $ob->username; + } + + function lookup_userid($username) + { + $result = mysql_query("SELECT userid FROM user_list WHERE username = '$username'"); + if(!$result || mysql_num_rows($result) != 1) + return null; + $ob = mysql_fetch_object($result); + return $ob->userid; + } + + function lookup_realname($userid) + { + $result = mysql_query("SELECT realname FROM user_list WHERE userid = $userid"); + if(!$result || mysql_num_rows($result) != 1) + return null; + $ob = mysql_fetch_object($result); + return $ob->realname; + } + + function lookup_email($userid) + { + $result = mysql_query("SELECT email FROM user_list WHERE userid = $userid"); + if(!$result || mysql_num_rows($result) != 1) + return null; + $ob = mysql_fetch_object($result); + return $ob->email; + } + + /* + * restore a user from the database + * returns 0 on success and an error msg on failure + */ + function restore($username, $password) + { + $result = mysql_query("SELECT stamp, userid, username, realname, ". + "created, status, perm FROM user_list WHERE ". + "username = '$username' AND ". + "password = password('$password')", $this->link); + //echo "RESTORE($username, $password) result=$result rows=".mysql_num_rows($result)."
\n"; + if(!$result) + return "Error: ".mysql_error($this->link); + + if(mysql_num_rows($result) == 0) + return "Invalid username or password"; + + list($this->stamp, $this->userid, $this->username, $this->realname, + $this->created, $status, $perm) = mysql_fetch_row($result); + + //echo "
User: $this->userid ($this->username, $this->realname)
\n"; + return 0; + } + + + function login($username, $password) + { + $result = $this->restore($username, $password); + + if($result != null) + return $result; + //echo "
LOGIN($this->username)
\n"; + //FIXME: update last_login here + return 0; + } + + /* + * create a new user + * returns 0 on success and an error msg on failure + */ + function create($username, $password, $realname, $email) + { + $result = mysql_query("INSERT INTO user_list VALUES ( NOW(), 0, ". + "'$username', password('$password'), ". + "'$realname', '$email', NOW(), 0, 0)", $this->link); + //echo "error: ".mysql_error(); + if(!$result) + return mysql_error($this->link); + return $this->restore($username, $password); + } + + // Update User Account; + function update($userid = 0, $password = null, $realname = null, $email = null) + { + if (!$userid) + return 0; + if ($password) + { + if (!mysql_query("UPDATE user_list SET password = password('$password') WHERE userid = $userid")) + return 0; + } + + if ($realname) + { + if (!mysql_query("UPDATE user_list SET realname = '".addslashes($realname)."' WHERE userid = $userid")) + return 0; + } + + if ($email) + { + if (!mysql_query("UPDATE user_list SET email = '".addslashes($email)."' WHERE userid = $userid")) + return 0; + } + return 1; + } + + /* + * remove the current, or specified user from the database + * returns 0 on success and an error msg on failure + */ + function remove($username = 0) + { + if($username == 0) + $username = $this->username; + + $result = mysql_query("DELETE FROM user_list WHERE username = '$username'", $this->link); + + if(!$result) + return mysql_error($this->link); + if(mysql_affected_rows($result) == 0) + return "No such user."; + return 0; + } + + + function done() + { + mysql_close($this->link); + } + + + function getpref($key, $def = null) + { + if(!$this->userid || !$key) + return $def; + + $result = mysql_query("SELECT * FROM user_prefs WHERE userid = $this->userid AND name = '$key'", $this->link); + if(!$result || mysql_num_rows($result) == 0) + return $def; + $ob = mysql_fetch_object($result); + return $ob->value; + } + + function setpref($key, $value) + { + if(!$this->userid || !$key || !$value) + return null; + + $result = mysql_query("DELETE FROM user_prefs WHERE userid = $this->userid AND name = '$key'"); + $result = mysql_query("INSERT INTO user_prefs VALUES($this->userid, '$key', '$value')"); + echo mysql_error(); + + return $result ? true : false; + } + + + /* + * check if this user has $priv + */ + function checkpriv($priv) + { + if(!$this->userid || !$priv) + return 0; + + $result = mysql_query("SELECT * FROM user_privs WHERE userid = $this->userid AND priv = '$priv'", $this->link); + if(!$result) + return 0; + return mysql_num_rows($result); + } + + function addpriv($priv) + { + if(!$this->userid || !$priv) + return 0; + + if($this->checkpriv($priv)) + return 1; + + $result = mysql_query("INSERT INTO user_privs VALUES ($this->userid, '$priv')", $this->link); + + return mysql_affected_rows($result); + } + + function delpriv($priv) + { + if(!$this->userid || !$priv) + return 0; + + $result = mysql_query("DELETE FROM user_privs WHERE userid = $this->userid AND priv = '$priv'", $this->link); + return mysql_num_rows($result); + } + + + /*========================================================================= + * + * App Owners + * + */ + function ownsApp($appId) + { + $result = mysql_query("SELECT * FROM appOwners WHERE ownerId = $this->userid AND appId = $appId"); + if($result && mysql_num_rows($result)) + return 1; // OK + return 0; // NOPE! + } + +} + + + + +function loggedin() +{ + global $current; + + if($current && $current->userid) + return true; + + return false; +} + +function havepriv($priv) +{ + global $current; + + if(!loggedin()) + return false; + + return $current->checkpriv($priv); +} + +function debugging() +{ + global $current; + + if(!loggedin()) + return false; + return $current->getpref("debug") == "yes"; +} + + +function makeurl($text, $url, $pref = null) +{ + global $current; + + if(loggedin()) + { + if($current->getpref($pref) == "yes") + $extra = "window='new'"; + } + return " $text \n"; +} + +// create a new random password +function generate_passwd($pass_len = 10) +{ + $nps = ""; + mt_srand ((double) microtime() * 1000000); + while (strlen($nps)<$pass_len) + { + $c = chr(mt_rand (0,255)); + if (eregi("^[a-z0-9]$", $c)) $nps = $nps.$c; + } + return ($nps); +} + +?> diff --git a/include/util.php b/include/util.php new file mode 100644 index 0000000..582f266 --- /dev/null +++ b/include/util.php @@ -0,0 +1,174 @@ +\n"; + exit; + } + mysql_select_db($apidb_db); + return $dbcon; +} + +function closedb() +{ + global $dbcon, $dbref; + + if(--$dbref) + return; + + mysql_close($dbcon); +} + +function querydb($query) +{ + $result = mysql_query($query); + if(!$result) + { + echo "
$query

\n"; + echo "A QUERY error occurred: ". + "".mysql_error()."

\n"; + } + return $result; +} + +function mysql_field_is_null($result, $row, $field) +{ + if(mysql_result($result, $row, $field) == null) + return 1; + return 0; +} + + +function read_string($filename) +{ + return join("", file($filename)); +} + + +function build_urlarg($vars) +{ + $arr = array(); + while(list($key, $val) = each($vars)) + { + if(is_array($val)) + { + while(list($idx, $value) = each($val)) + { + //echo "Encoding $key / $value
"; + $arr[] = rawurlencode($key."[]")."=".rawurlencode($value); + } + } + else + $arr[] = $key."=".rawurlencode($val); + } + return implode("&", $arr); +} + + +function add_option_menu($options, $label, $id) +{ + echo "

\n"; + echo "\n"; + echo "\n"; + echo "

\n"; +} + + +/* + * return all keys of a mapping as an array + */ +function keys($arr) +{ + $res = array(); + while(list($k, $v) = each($arr)) + $res[] = $k; + return $res; +} + +/* + * return all values of a mapping as an array + */ +function values($arr) +{ + $res = array(); + while(list($k, $v) = each($arr)) + $res[] = $v; + return $res; +} + + +/* + * format date + */ +function makedate($time) +{ + return date("F d, Y H:i:s", $time); +} + + +function get_remote() +{ + global $REMOTE_HOST, $REMOTE_ADDR; + + if($REMOTE_HOST) + $ip = $REMOTE_HOST; + else + $ip = $REMOTE_ADDR; + + return $ip; +} + +function htmlify_urls($text) +{ + //FIXME: wonder what the syntax is, this doesn't seem to work + // $text = strip_tags($text, ",,,
    ,
  • "); + + // html-ify urls + $urlreg = "([a-zA-Z]+://([^\t\r\n ]+))"; + $text = ereg_replace($urlreg, " \\2 ", $text); + + $emailreg = "([a-zA-Z0-9_%+.-]+@[^\t\r\n ]+)"; + $text = ereg_replace($emailreg, " \\1", $text); + + $text = str_replace("\n", "
    ", $text); + + return $text; +} + +// open file and display contents of selected tag +function get_xml_tag ($file, $mode = null) +{ + if ($mode and file_exists($file)) + { + $fp = @fopen($file, "r"); + $data = fread($fp, filesize($file)); + @fclose($fp); + if (eregi("<" . $mode . ">(.*)", $data, $out)) + { + return $out[1]; + } + } + else + { + return null; + } +} + +?> diff --git a/include/vote.php b/include/vote.php new file mode 100644 index 0000000..3360fcd --- /dev/null +++ b/include/vote.php @@ -0,0 +1,199 @@ +userid; + else + return 0; + } + $result = mysql_query("SELECT * FROM appVotes WHERE appId = $appId AND userId = $userId"); + return mysql_num_rows($result); +} + +/* + * total votes by userId + */ +function vote_count_user_total($userId = null) +{ + global $current; + + if(!$userId) + { + if(loggedin()) + $userId = $current->userid; + else + return 0; + } + $result = mysql_query("SELECT * FROM appVotes WHERE userId = $userId"); + return mysql_num_rows($result); +} + +/* + * total votes for appId + */ +function vote_count_app_total($appId) +{ + $result = mysql_query("SELECT * FROM appVotes WHERE appId = $appId"); + return mysql_num_rows($result); +} + + + + +/* + * add a vote for appId + */ +function vote_add($appId, $slot, $userId = null) +{ + global $current; + global $MAX_VOTES; + + if(!$userId) + { + if(loggedin()) + $userId = $current->userid; + else + return; + } + + //if(vote_count_user_total($userId) >= $MAX_VOTES) + // return; + vote_remove($appId, $slot, $userId); + mysql_query("INSERT INTO appVotes VALUES (null, null, $appId, $userId, $slot)"); +} + + +/* + * remove vote for appId + */ +function vote_remove($appId, $slot, $userId = null) +{ + global $current; + + if(!$userId) + { + if(loggedin()) + $userId = $current->userid; + else + return; + } + mysql_query("DELETE FROM appVotes WHERE appId = $appId AND userId = $userId AND slot = $slot"); +} + +function vote_get_user_votes($userId = null) +{ + global $current; + + if(!$userId) + { + if(loggedin()) + $userId = $current->userid; + if(!$userId) + return array(); + } + $result = mysql_query("SELECT * FROM appVotes WHERE userId = $userId"); + if(!$result) + return array(); + + $obs = array(); + while($ob = mysql_fetch_object($result)) + $obs[$ob->slot] = $ob; + return $obs; +} + +function vote_menu() +{ + global $appId; + global $apidb_root; + + $m = new htmlmenu("Votes","updatevote.php"); + + $votes = vote_get_user_votes(); + + if($votes[1]) + { + $str = " App #".$votes[1]->appId.""; + $m->add(" ".$str); + } + else + $m->add(" No App Selected"); + + if($votes[2]) + { + $str = " App #".$votes[2]->appId.""; + $m->add(" ".$str); + } + else + $m->add(" No App Selected"); + + if($votes[3]) + { + $str = " App #".$votes[3]->appId.""; + $m->add(" ".$str); + } + else + $m->add(" No App Selected"); + + $m->addmisc(" "); + + $m->add(""); + $m->add(""); + + $m->addmisc(""); + + $m->add("View Results", $apidb_root."votestats.php"); + $m->add("Voting Help", $apidb_root."help/?topic=voting"); + + $m->done(1); +} + + +function dump($arr) +{ + while(list($key, $val) = each($arr)) + { + echo "$key => $val
    \n"; + } +} + +function vote_update($vars) +{ + global $current; + + //FIXME this doesn't work since msgs only work when logged in + if(!$current) + { + addmsg("You must be logged in to vote", "red"); + return; + } + + dump($vars); + echo "
    \n"; + + if($vars["vote"]) + { + addmsg("Registered vote for App #".$vars["appId"], "green"); + vote_add($vars["appId"], $vars["slot"]); + } + else + if($vars["clear"]) + { + addmsg("Removed vote for App #".$vars["appId"], "green"); + vote_remove($vars["appId"], $vars["slot"]); + } +} + + +?> diff --git a/index.php b/index.php new file mode 100644 index 0000000..56b49ee --- /dev/null +++ b/index.php @@ -0,0 +1,70 @@ + + + Wine AppDB + +

    Welcome

    + +

    This is the Wine Application Database. From here you get info on application + compatibility with Wine. For developers, you can get information on the APIs used in an + application.

    + +

    Most of the features of the Application database require that you have a user account and + are logged in. Some of the benefits of membership are:

    + +

      +
    • Ability to Vote on Favorite Applications
    • +
    • Access to the Application Rating System. Rate the apps that "Don't Suck"
    • +
    • Ability to customize the View of the Apps DB and Comment System
    • +
    • Take Credit for your witty posts.
    • +
    + +

    So what are you waiting for, [login now]. Your help in + stomping out Wine issues will be greatly appreciated.

    + +

    + If you have anything to contribute (screenshots, howtos), contact us at: + appdb@winehq.com +

    +hits; + + $voteQuery = "SELECT appVotes.appId, appName, count(userId) as count ". + "FROM appVotes, appFamily ". + "WHERE appVotes.appId = appFamily.appId ". + "GROUP BY appId ORDER BY count DESC LIMIT 1"; + $result = mysql_query($voteQuery); + $ob = mysql_fetch_object($result); + + $voteAppId = $ob->appId; + $voteAppName = $ob->appName; + + + echo "There are $numApps applications currently in the database with\n"; + echo "$voteAppName being the\n"; + echo "top voted application.\n"; + + echo "

     

    \n"; + +apidb_footer(); + + + + +?> diff --git a/noteview.php b/noteview.php new file mode 100644 index 0000000..bb84d92 --- /dev/null +++ b/noteview.php @@ -0,0 +1,60 @@ +add("Edit this Note", $apidb_root."admin/editAppNote.php?noteId=$noteId"); + $m->done(); +} + +//do query +$result = mysql_query("SELECT noteTitle, noteDesc FROM appNotes WHERE noteId = $noteId"); +$ob = mysql_fetch_object($result); + +//die if error +if(!$result || mysql_num_rows($result) == 0) +{ + // error + errorpage("No Note Found","The selected note was not found."); + exit; +} + +//display admin menu +if(loggedin() && (havepriv("admin") || $current->ownsApp($appId))) { + apidb_sidebar_add("admin_menu"); +} + +//show page +apidb_header(); + +echo html_frame_start("View Note - $ob->noteTitle ","80%"); + +echo add_br(stripslashes($ob->noteDesc)); + +echo html_frame_end(); + +if ($versionId) +{ + echo html_back_link(1,"appview.php?appId=$appId&versionId=$versionId"); +} +else +{ + echo html_back_link(1,"appview.php?appId=$appId"); +} + +apidb_footer(); + +?> diff --git a/path.php b/path.php new file mode 100644 index 0000000..2a71d45 --- /dev/null +++ b/path.php @@ -0,0 +1,3 @@ + diff --git a/preferences.php b/preferences.php new file mode 100644 index 0000000..3111000 --- /dev/null +++ b/preferences.php @@ -0,0 +1,106 @@ +name == "query:mode") + continue; + if($r->name == "sidebar") + continue; + if($r->name == "window:query") + continue; + if($r->name == "query:hide_header") + continue; + if($r->name == "query:hide_sidebar") + continue; + if($r->name == "debug") + continue; + } + + $input = html_select("pref_$r->name", explode('|', $r->value_list), + $current->getpref($r->name, $r->def_value)); + echo html_tr(array("  $r->description", $input)); + } +} + +function show_user_fields() +{ + global $current; + $user = new User(); + + $ext_username = $current->username; + $ext_realname = $user->lookup_realname($current->userid); + $ext_email = $user->lookup_email($current->userid); + + include(BASE."include/"."form_edit.php"); +} + +if($HTTP_POST_VARS) +{ + global $ext_username, $ext_password1, $ext_password2, $ext_realname, $ext_email; + global $current; + + $user = new User(); + + while(list($key, $value) = each($HTTP_POST_VARS)) + { + if(!ereg("^pref_(.+)$", $key, $arr)) + continue; + $current->setpref($arr[1], $value); + } + + if ($ext_password == $ext_password2) + { + $passwd = $ext_password; + } + else if ($ext_password) + { + addmsg("The Passwords you entered did not match.", "red"); + } + + if ($user->update($current->userid, $passwd, $ext_realname, $ext_email)) + { + addmsg("Preferences Updated", "green"); + } + else + { + addmsg("There was a problem updating your userinfo", "red"); + } +} + +apidb_header("User Preferences"); + +echo "
    \n"; +echo html_frame_start("Preferences for $current->username", "80%"); +echo html_table_begin("width='100%' border=0 align=left cellspacing=0 class='box-body'"); + +show_user_fields(); +build_prefs_list(); + +echo html_table_end(); +echo html_frame_end(); +echo "

    \n"; +echo "
    \n"; + + +apidb_footer(); +?> diff --git a/screenshots.php b/screenshots.php new file mode 100644 index 0000000..dba9d94 --- /dev/null +++ b/screenshots.php @@ -0,0 +1,103 @@ +\n"; + while($ob = mysql_fetch_object($result)) + { + //set img tag + $imgSRC = ''.$ob->description.''; + + //get image size + $size = getimagesize("data/screenshots/".$ob->url); + + //generate random tag for popup window + $randName = generate_passwd(5); + + //set image link based on user pref + $img = ''.$imgSRC.''; + if (loggedin()) + { + if ($current->getpref("window:screenshot") == "no") + { + $img = ''.$imgSRC.''; + } + } + + //display image + echo "\n"; + + //end row if counter of 3 + if ($c % 3 == 0) { echo "\n"; } + + $c++; + } + echo "
    \n"; + echo html_frame_start(substr(stripslashes($ob->description),0,20),128,"",0); + echo $img; + + //show admin delete link + if(loggedin() && (havepriv("admin") || $current->ownsApp($appId))) + { + echo ""; + } + + echo html_frame_end(" "); + echo "

    \n"; + + + echo html_frame_end("Click thumbnail to view image in new window."); + + echo html_back_link(1); + + apidb_footer(); + +} + +?> diff --git a/scripts.js b/scripts.js new file mode 100644 index 0000000..5f9ee23 --- /dev/null +++ b/scripts.js @@ -0,0 +1,18 @@ + +function openWin(fileToOpen,nameOfWindow,width,height) { + myWindow = window.open("",nameOfWindow,"menubar=no,scrollbars=yes,status=no,width="+width+",height="+height); + myWindow.document.open(); + myWindow.document.write('ScreenShot Viewer') + myWindow.document.write(''); + myWindow.document.write(''); + myWindow.document.write(''); + myWindow.document.close(); +} + +function deleteURL(text, url) { + if (confirm(text)) { + self.location = url; + } +} + + diff --git a/search.php b/search.php new file mode 100644 index 0000000..16282e8 --- /dev/null +++ b/search.php @@ -0,0 +1,66 @@ +\n\n"; + + echo "
Application NameDescriptionNo. Versions
".html_ahref($ob->appName,"appview.php?appId=$ob->appId")."$desc  $y->versions  
$c match(es) found
\n\n"; +} + +apidb_footer(); + +?> diff --git a/stdquery.php b/stdquery.php new file mode 100644 index 0000000..589b4b4 --- /dev/null +++ b/stdquery.php @@ -0,0 +1,125 @@ +getpref("query:hide_header") == "yes") + disable_header(); + if($current->getpref("query:hide_sidebar") == "yes") + disable_sidebar(); +} + + +// create $vars object +$vars = $HTTP_GET_VARS; +$qc = new qclass(); +$qc->process($vars); +$query = $qc->get_query(); + + +// set default lines per page +if(!$linesPerPage) +{ + $linesPerPage = 20; +} +$vars["linesPerPage"] = $linesPerPage; + + +// set default currrent posistion +if(!$curPos) +{ + $curPos = 0; +} +$vars["curPos"] = $curPos; + + +// Get total count +if($totalCount == 0) +{ + $tempResult = mysql_query($query); + if(!$tempResult) + { + echo "$query
\n"; + echo "An error occurred: ".mysql_error()."

"; + exit; + } + $totalCount = mysql_num_rows($tempResult); + $vars["totalCount"] = $totalCount; + mysql_free_result($tempResult); +} + +// No data +if($totalCount == 0) +{ + if(debugging()) + { + echo $query; + echo "

"; + } + + echo "Your query returned no data.\n"; + return; +} + +$endPos=$curPos+$linesPerPage; + + +if($verbose) +{ + // verbose view (edit mode) + + include(BASE."include/"."tableve.php"); + if(!$mode) + $mode = "view"; + apidb_header(ucfirst($mode)." Query"); + + $t = new TableVE($mode); + $query = str_replace("\\", "", $query); + + $endPos = $curPos + $linesPerPage; + $query .= " LIMIT $curPos,$endPos"; + + if(debugging()) + echo "$query

\n"; + + add_pn_buttons($vars, $endPos); + echo "
curPos: $curPos
linesPerPage: $linesPerPage
totalCount: $totalCount
"; + + if($mode == "edit") + $t->edit($query); + else + $t->view($query); + + add_pn_buttons($vars, $endPos); + + apidb_footer(); +} +else +{ + // normal view (user view) + + apidb_header("Query Results"); + + include(BASE."include/"."query_inc.php"); + + twinedb_query($query, $vars); + + apidb_footer(); +} + + +?> diff --git a/support.php b/support.php new file mode 100644 index 0000000..3212d26 --- /dev/null +++ b/support.php @@ -0,0 +1,42 @@ + +

Who Can Help Me Out?

+ +

+ If you have questions, comments on the Wine Application Database, you can contact + us at appdb@winehq.com. +

+ +

+ If you notice something that seems to be wrong, or busticated, there is a way you can + help us out.
+ We also have a Bug Tracking Database + where you can register bugs. This is the best way to get problems fixed. You can go directly + to the App DB Bug Database by following this + link. +

+ +

+ If you need more information on the Wine Project itself, there are plenty of resources. +

+ + + diff --git a/tables/.htaccess b/tables/.htaccess new file mode 100644 index 0000000..c9c4d1b --- /dev/null +++ b/tables/.htaccess @@ -0,0 +1,2 @@ +deny from all + diff --git a/tables/appdb_tables.sql b/tables/appdb_tables.sql new file mode 100644 index 0000000..481cd3d --- /dev/null +++ b/tables/appdb_tables.sql @@ -0,0 +1,246 @@ +use apidb; + +drop table vendor; +drop table appFamily; +drop table appVersion; +drop table userExperience; +drop table apiUsage; +drop table appCategory; +drop table appHitStats; +drop table catHitStats; +drop table appOwners; +drop table appComments; +drop table appData; + + +/* + * vendor information + */ +create table vendor ( + vendorId int not null auto_increment, + vendorName varchar(100) not null, + vendorURL varchar(200), + key(vendorId) +); + + +/* + * application + */ +create table appFamily ( + appId int not null auto_increment, + appName varchar(100) not null, + vendorId int not null, + keywords text, + description text, + webPage varchar(100), + catId int, + key(appId) +); + + +/* + * a version of an application + */ +create table appVersion ( + versionId int not null auto_increment, + appId int not null, + versionName varchar(100) not null, + keywords text, + description text, + webPage varchar(100), + rating_windows float default 0.0, + rating_fake float default 0.0, + key(versionId) +); + +create table appQueue ( + queueId int not null auto_increment, + queueName varchar(100) not null, + queueVersion varchar(100) not null, + queueVendor varchar(100) not null, + queueDesc text, + queueEmail varchar(100), + queueURL varchar(100), + queueImage varchar(100) not null, + key(queueId) +); + +create table userExperience ( + uExpId int not null auto_increment, + versionId int not null, + userComments text, + testPlatform varchar(100), + wineVintage varchar(100), + entryDate timestamp not null, + userName text not null, + wineCfgFile text, + key(uExpId) +); + +create table apiUsage ( + apiUsageId int not null auto_increment, + versionId int not null, + apiid int(11) not null, + key(apiUsageId) +); + + +/* + * application category + */ +create table appCategory ( + catId int not null auto_increment, + catName varchar(64) not null, + catDescription text, + catParent int default 0, + key(catId) +); + + +/* + * not used yet + */ +create table appCrosslink ( + appId int not null, + catId int not null, + key(appId), + index(catId) +); + + +/* + * bundleId is the appId of the 'owner app' + */ +create table appBundle ( + bundleId int not null, + appId int not null, + key(bundleId), + index(appId) +); + + +/* + * appHitStats and catHitStats are to record statistics + */ +create table appHitStats ( + appHitId int not null auto_increment, + time timestamp, + ip varchar(16), + appId int not null, + count int, + key(appHitId) +); + +create table catHitStats ( + catHitId int not null auto_increment, + time timestamp, + ip varchar(16), + catId int not null, + count int, + key(catHitId) +); + + + +/* + * application <> owner mapping + */ +create table appOwners ( + appId int not null, + ownerId int not null, + key(appId) +); + + +/* + * user comments + */ +create table appComments ( + time timestamp, + commentId int not null auto_increment, + parentId int default 0, + appId int not null, + versionId int default 0, + userId int, + hostname varchar(80), + subject varchar(128), + body text, + score int, + key(commentId), + index(appId), + index(versionId) +); + + + +/* + * links to screenshots and other stuff + */ +create table appData ( + id int not null auto_increment, + appId int not null, + versionId int default 0, + type enum('image', 'url'), + description text, + url varchar(255), + key(id), + index(appId), + index(versionId) +); + + +/* + * allow users to vote for apps, as in, request that an app gets better support + */ +create table appVotes ( + id int not null auto_increment, + time timestamp, + appId int not null, + userId int not null, + slot int not null, + key(id), + index(appId), + index(userId) +); + + +/* + * app ratings + */ +create table appRating ( + id int not null auto_increment, + time timestamp, /* we might wanna expire old ratings */ + versionId int not null, + userId int not null, + system enum('windows', 'fake'), + score int not null, + key(id), + index(versionId), + index(userId) +); + + +/* + * application notes + */ +create table appNotes ( + noteId int not null auto_increment, + noteTitle varchar(255), + noteDesc text, + appId int not null, + versionId int not null, + key(noteId) +); + +/* + * + */ +create table sessionMessages ( + id int not null auto_increment, + time timestamp, + sessionId varchar(32), + message text, + key(id), + index(sessionId) +); diff --git a/tables/appratings.sql b/tables/appratings.sql new file mode 100644 index 0000000..b509b49 --- /dev/null +++ b/tables/appratings.sql @@ -0,0 +1,7 @@ +SELECT appVersion.appId, appVersion.versionId, appName, versionName, avg(score) as rating, count(appVersion.versionId) as hits +FROM appRating, appFamily, appVersion +WHERE (appVersion.versionId = appRating.versionId +AND appFamily.appId = appVersion.appId) +AND system = 'fake' AND rating = 5 +GROUP BY appVersion.versionId +ORDER BY appName ASC diff --git a/tables/banner.sql b/tables/banner.sql new file mode 100644 index 0000000..08b824f --- /dev/null +++ b/tables/banner.sql @@ -0,0 +1,12 @@ +CREATE TABLE banner ( + id int not null, + desc text, + img varchar(255), + url varchar(255), + alt varchar(255), + imp int not null, + clk int not null, + lastmod timestamp, + + primary key(id) +) diff --git a/tables/prefs_list.sql b/tables/prefs_list.sql new file mode 100644 index 0000000..e06bb19 --- /dev/null +++ b/tables/prefs_list.sql @@ -0,0 +1,19 @@ +CREATE TABLE prefs_list ( + id int auto_increment not null, + name varchar(32), + def_value text, + value_list text, + description text, + + primary key(id) +); + +INSERT INTO prefs_list VALUES (0, 'debug', 'no', 'yes|no', 'Enable debugging information'); +INSERT INTO prefs_list VALUES (0, 'sidebar', 'left', 'left|right', 'Sidebar location'); +INSERT INTO prefs_list VALUES (0, 'window:query', 'no', 'yes|no', 'Display query results in a new window'); +INSERT INTO prefs_list VALUES (0, 'window:help', 'no', 'yes|no', 'Display help in a new window'); +INSERT INTO prefs_list VALUES (0, 'window:offsite', 'no', 'yes|no', 'Display offsite URLs in a new window'); + +INSERT INTO prefs_list VALUES (0, 'query:mode', 'view', 'view|edit', 'Default API details mode'); +INSERT INTO prefs_list VALUES (0, 'query:hide_header', 'no', 'yes|no', 'Hide apidb header in query results'); +INSERT INTO prefs_list VALUES (0, 'query:hide_sidebar', 'no', 'yes|no', 'Hide apidb sidebar in query results'); diff --git a/tables/user_list.sql b/tables/user_list.sql new file mode 100644 index 0000000..48ddfe9 --- /dev/null +++ b/tables/user_list.sql @@ -0,0 +1,19 @@ + +create table user_list ( + stamp timestamp not null, + userid int not null auto_increment, + username text not null, + password text not null, + realname text not null, + email text not null, + created datetime not null, + status int(4), + perm int(4), + unique key(userid), + unique(username(12)) +); + +insert into user_list values (NOW(), 0, 'int', password('testing'), 'Charles Loep', + 'charles@codeweavers.com', NOW(), 0, 0xffffffff); +update user_list set userid = 1000 where username = 'int'; + diff --git a/tables/user_prefs.sql b/tables/user_prefs.sql new file mode 100644 index 0000000..a2be08f --- /dev/null +++ b/tables/user_prefs.sql @@ -0,0 +1,7 @@ +CREATE TABLE user_prefs ( + userid int not null, + name varchar(64) not null, + value text, + key(userid), + key(name) +); diff --git a/tables/user_privs.sql b/tables/user_privs.sql new file mode 100644 index 0000000..5f53557 --- /dev/null +++ b/tables/user_privs.sql @@ -0,0 +1,6 @@ +CREATE TABLE user_privs ( + userid int not null, + priv varchar(64) not null, + primary key(userid) +); + diff --git a/updaterating.php b/updaterating.php new file mode 100644 index 0000000..0325d6d --- /dev/null +++ b/updaterating.php @@ -0,0 +1,18 @@ + diff --git a/updatevote.php b/updatevote.php new file mode 100644 index 0000000..4c712d3 --- /dev/null +++ b/updatevote.php @@ -0,0 +1,15 @@ + diff --git a/vendorview.php b/vendorview.php new file mode 100644 index 0000000..80ecce6 --- /dev/null +++ b/vendorview.php @@ -0,0 +1,75 @@ +vendorName
\n"; + +if ($vendor->vendorURL) { + echo "Vendor URL: $vendor->vendorURL
\n"; +} + +$result = mysql_query("SELECT * FROM appFamily WHERE vendorId = $vendorId ORDER BY appName"); +if($result) +{ + echo "
Applications by $vendor->vendorName
    \n"; + while($app = mysql_fetch_object($result)) + { + echo "
  1. $app->appName
  2. \n"; + } + echo "
\n"; +} + +echo html_frame_end(); +echo html_back_link(1); +apidb_footer(); + + + +// SUBS // + +//admin menu for sidebar +function admin_menu() +{ + global $vendorId; + + $m = new htmlmenu("Admin"); + $m->add("Edit this vendor", "admin/editVendor.php?vendorId=$vendorId"); + $m->done(); +} + +?> diff --git a/votestats.php b/votestats.php new file mode 100644 index 0000000..370fed2 --- /dev/null +++ b/votestats.php @@ -0,0 +1,45 @@ +Application Name\n"; + echo "Votes\n"; + + $c = 1; + while($row = mysql_fetch_object($result)) + { + if ($c % 2 == 1) { $bgcolor = "color0"; } else { $bgcolor = "color1"; } + $link = "$row->appName"; + echo "$c. $link $row->count \n"; + $c++; + } + echo html_table_end(); + echo html_frame_end(); + + echo "
What does this screen mean?
\n"; + +} +else +{ + echo "Error: " . mysql_error(); +} + +apidb_footer(); + +?>