=== added directory 'project_verify_package'
=== added file 'project_verify_package/project_verify_package.info'
--- project_verify_package/project_verify_package.info	1970-01-01 00:00:00 +0000
+++ project_verify_package/project_verify_package.info	2009-12-03 18:49:56 +0000
@@ -0,0 +1,8 @@
+; $Id: $
+name = Project verify package
+description = drupal.org specific verification helpers for the project packaging system.
+package = Project
+dependencies[] = project
+dependencies[] = project_release
+dependencies[] = project_package
+core = 6.x
\ No newline at end of file

=== added file 'project_verify_package/project_verify_package.install'
--- project_verify_package/project_verify_package.install	1970-01-01 00:00:00 +0000
+++ project_verify_package/project_verify_package.install	2009-12-03 19:48:49 +0000
@@ -0,0 +1,13 @@
+<?php
+// $Id: $
+
+/**
+* @file
+* Install functions for project_verify_package module.
+*/
+
+function project_verify_package_install() {
+  // Make this module heavier than project_release module.
+  $weight = db_result(db_query("SELECT weight FROM {system} WHERE name = 'project_release'"));
+  db_query("UPDATE {system} SET weight = %d WHERE name = 'project_verify_package'", $weight + 1);
+}

=== added file 'project_verify_package/project_verify_package.module'
--- project_verify_package/project_verify_package.module	1970-01-01 00:00:00 +0000
+++ project_verify_package/project_verify_package.module	2009-12-04 02:06:18 +0000
@@ -0,0 +1,193 @@
+<?php
+
+// $Id: $
+
+/**
+* @file
+* drupal.org specific verification helpers for the project packaging system.
+*/
+
+// The full path of the drush executable.
+define('PROJECT_VERIFY_PACKAGE_DRUSH_BIN', '/Users/hunmonk/bin/drush');
+// The full path of the directory that contains the drush_make
+// extensions.
+define('PROJECT_VERIFY_PACKAGE_DRUSH_MAKE_PATH', '/Users/hunmonk/.drush/drush_make');
+// The name of the .make file to convert to or verify.
+define('PROJECT_VERIFY_PACKAGE_MAKE_FILE', 'drupal-org.make');
+define('PROJECT_VERIFY_PACKAGE_PROFILE_TID', 2);
+
+/**
+ * Implement hook_menu().
+ */
+function project_verify_package_menu() {
+  $items = array();
+
+  // 'Convert/verify .make files' link on profile project pages.
+  $items['node/%node/convert-verify-make-file'] = array(
+    'title' => 'Convert/verify .make files',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('project_verify_package_convert_verify_make_file_form', 1),
+    'access callback' => 'node_access',
+    'access arguments' => array('create', 'project_release'),
+    'type' => MENU_CALLBACK,
+  );
+
+  return $items;
+}
+
+/**
+ * Builds a form used to submit .make files to be converted/verified.
+ */
+function project_verify_package_convert_verify_make_file_form(&$form_state, $node) {
+  $form = array();
+
+  $options = array(
+    'convert' => t('Convert an existing .make file to @makefile format', array('@makefile' => PROJECT_VERIFY_PACKAGE_MAKE_FILE)),
+    'verify' => t('Verify that an existing .make file is in @makefile format', array('@makefile' => PROJECT_VERIFY_PACKAGE_MAKE_FILE)),
+  );
+  $form['operation'] = array(
+    '#title' => t('Select the operation to perform'),
+    '#type' => 'radios',
+    '#options' => $options,
+    '#default_value' => empty($form_state['storage']['operation']) ? '' : $form_state['storage']['operation'],
+    '#required' => TRUE,
+  );
+  $form['makefile'] = array(
+    '#title' => t('Paste the contents of the .make file here'),
+    '#type' => 'textarea',
+    '#default_value' => empty($form_state['storage']['makefile']) ? '' : $form_state['storage']['makefile'],
+    '#required' => TRUE,
+  );
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Process'),
+  );
+
+  return $form;
+}
+
+/**
+ * Submit handler for for the convert/verify .make file form.
+ */
+function project_verify_package_convert_verify_make_file_form_submit($form, &$form_state) {
+  $operation = $form_state['values']['operation'];
+  $makefile = $form_state['values']['makefile'];
+  // Could be dangerous to blindly take the operation from the form, so
+  // explicitly look for it.
+  switch ($operation) {
+    case 'convert':
+      $command = 'convert makefile';
+      break;
+    case 'verify':
+      $command = 'verify makefile';
+      break;
+  }
+  if (isset($command)) {
+    // Run the drush command.
+    list ($output, $return) = project_verify_package_run_drush_via_pipe($command, $makefile);
+
+    // Assemble the output.  We might need both the raw output to put back into
+    // the text area, or escaped output to put into a user message, so build
+    // them both here.
+    $escaped_output_array = array();
+    $raw_output_array = array();
+    foreach ($output as $line) {
+      $line = trim($line);
+      if (!empty($line)) {
+        $escaped_output_array[] = check_plain($line);
+        $raw_output_array[] = $line;
+      }
+    }
+    $escaped_output = implode("\n", $escaped_output_array);
+    $raw_output = implode("\n", $raw_output_array);
+
+    // Operation failed.
+    if ($return) {
+      $message = t('Errors occured when attempting to %operation the .make file.  Correct the errors listed below and try again.', array('%operation' => $operation));
+      $message = nl2br($message . "\n\n" . $escaped_output);
+
+      drupal_set_message($message, 'error');
+      // For failures, put the original .make file back in the .make file text
+      // area so it can be edited/adjusted.
+      $form_state['storage']['makefile'] = $makefile;
+    }
+    // Operation succeeded.
+    else {
+      $message = t('The attempt to %operation the make file was successful.  Review the results below.', array('%operation' => $operation));
+      // Where we put returned output and the original makefile depends on the
+      // operation.
+      switch ($operation) {
+        // Converted .make files get the raw output put into the text area.
+        case 'convert':
+          $form_state['storage']['makefile'] = $raw_output;
+          break;
+        // Verified .make files get the submitted .make file put back into the
+        // textarea, and the output of the verify command added to the user
+        // message.
+        case 'verify':
+          $message = nl2br($message . "\n\n" . $escaped_output);
+          $form_state['storage']['makefile'] = $makefile;
+          break;
+      }
+      drupal_set_message($message);
+    }
+    // Don't forget the operation, in case the user wants to re-run.
+    $form_state['storage']['operation'] = $operation;
+  }
+  // If we made it here, somebody is trying to do something nasty, so log it.
+  else {
+    watchdog('package', t('Malicious attempt to submit command %command to server.', array('%command' => $command)), array(), WATCHDOG_ERROR);
+  }
+
+}
+
+/**
+ * Implemenation of hook_project_page_link_alter().
+ *
+ * Note:  This is *not* an implementation of hook_link_alter().
+ */
+function project_verify_package_project_page_link_alter(&$links, $node) {
+  // Insert the link on all project nodes that:
+  //   1. Have releases enabled.
+  //   2. Are an installation profile project type.
+  if (!empty($node->project_release['releases']) && !empty($node->taxonomy[PROJECT_VERIFY_PACKAGE_PROFILE_TID])) {
+    $links['project_release']['links']['project_verify_package_convert_verify_make_file_link'] = l(t('Convert/verify release .make files'), "node/$node->nid/convert-verify-make-file");
+  }
+}
+
+/**
+ * Runs a drush command via pipes, so that nothing touches the I/O subsystem.
+ *
+ * @param $ommand
+ *   The drush command to send.
+ * @param $input
+ *   The input to pipe to the drush command.
+ * @return
+ *   An array, the first element is the command output, and second element is
+ *   the command return value.
+ */
+function project_verify_package_run_drush_via_pipe($command, $input) {
+
+  // escapseshellcmd() seems to clobber the newline characters, so we need to
+  // break apart the input, excape each line, then reassemble it.
+  $piped_lines = array();
+  $input_lines = explode("\n", $input);
+  foreach ($input_lines as $line) {
+    $line = trim($line);
+    if (!empty($line)) {
+      $line = escapeshellcmd($line);
+      // escapseshellcmd() clobbers the brackets, and we need them.
+      // TODO: can we really know this is secure?
+      $line = str_replace(array('\[', '\]'), array('[', ']'), $line);
+  	  $piped_lines[] = $line;
+    }
+  }
+  $piped_input = 'echo "' . implode("\n", $piped_lines) . '"';
+  $drush = PROJECT_VERIFY_PACKAGE_DRUSH_BIN . ' --include=' . PROJECT_VERIFY_PACKAGE_DRUSH_MAKE_PATH;
+
+  // drush expects a terminal, so give it one.
+  putenv("TERM=vt100");
+  // Made sure we grab stderr, too...
+  exec("TERM=vt100; $piped_input | $drush $command - 2>&1", $output, $return_value);
+  return array($output, $return_value);
+}

