? .cvsignore
? 1033378-urlencode-subject.patch
? privatemsg.views_.patch
? privatemsg_encode_subject_and_with_clean_url_decode_check.patch
? privatemsg_encode_subject_with_tests.patch
? privatemsg_encode_subject_with_tests_without_debug.patch
? privatemsg_textfield.patch
Index: privatemsg.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg.module,v
retrieving revision 1.161
diff -u -p -r1.161 privatemsg.module
--- privatemsg.module	17 Jan 2011 10:37:53 -0000	1.161
+++ privatemsg.module	20 Jan 2011 11:31:28 -0000
@@ -1839,7 +1839,13 @@ function privatemsg_get_link($recipients
   }
   $url = privatemsg_get_dynamic_url_prefix($account->uid) . '/new/'. implode(',', $validated);
   if (!is_null($subject)) {
-    $url .= '/'. $subject;
+   // Not using drupal_urlencode() because we need to encode / too.
+   $subject = rawurlencode($subject);
+   if (variable_get('clean_url', '0')) {
+     // mod_rewrite decodes /, encode them twice.
+     $subject = str_replace('%2F', '%252F', $subject);
+   }
+   $url .= '/' . $subject;
   }
   return $url;
 }
Index: privatemsg.pages.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg.pages.inc,v
retrieving revision 1.25
diff -u -p -r1.25 privatemsg.pages.inc
--- privatemsg.pages.inc	17 Jan 2011 10:37:53 -0000	1.25
+++ privatemsg.pages.inc	20 Jan 2011 11:31:29 -0000
@@ -207,6 +207,12 @@ function privatemsg_new(&$form_state, $r
     $recipients = array();
   }
 
+  // Subject has / encoded twice if clean urls are enabled to get it through
+  // mod_rewrite and the menu system. Decode it once more.
+  if (variable_get('clean_url', '0')) {
+    $subject = str_replace('%2F', '/', $subject);
+  }
+
   $usercount = 0;
   $to = array();
   $to_plain = array();
Index: tests/privatemsgapi.test
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/tests/privatemsgapi.test,v
retrieving revision 1.7
diff -u -p -r1.7 privatemsgapi.test
--- tests/privatemsgapi.test	17 Aug 2010 13:05:41 -0000	1.7
+++ tests/privatemsgapi.test	20 Jan 2011 11:31:29 -0000
@@ -114,4 +114,58 @@ class PrivatemsgAPITestCase extends Drup
     $this->assertEqual($errormessage, $resultf2['messages']['error'][0], 'API denied to send message from user without permission');
 
   }
-}
\ No newline at end of file
+
+  /**
+   * Test various use cases for privatemsg_get_link().
+   */
+  function testGetLink() {
+    $author      = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg'));
+    $recipient1  = $this->drupalCreateUser(array('read privatemsg'));
+    $recipient2  = $this->drupalCreateUser(array('read privatemsg'));
+    $recipient3  = $this->drupalCreateUser(array('read privatemsg', 'allow disabling privatemsg'));
+    $recipient4  = $this->drupalCreateUser();
+
+    $this->drupalLogin($author);
+
+    $this->drupalGet(privatemsg_get_link(array($recipient1)));
+    $this->assertFieldByName('recipient', $recipient1->name . ' [user]');
+
+    $this->drupalGet(privatemsg_get_link(array($recipient1, $recipient2)));
+    $this->assertFieldByName('recipient', $recipient1->name . ' [user], ' . $recipient2->name . ' [user]');
+
+    $this->drupalGet(privatemsg_get_link(array($recipient1, $recipient2), $author));
+    $this->assertFieldByName('recipient', $recipient1->name . ' [user], ' . $recipient2->name . ' [user]');
+
+    $this->drupalGet(privatemsg_get_link(array($recipient1, $recipient2), $author, $subject = 'Str/"ang\\w3//'));
+    $this->assertFieldByName('recipient', $recipient1->name . ' [user], ' . $recipient2->name . ' [user]');
+    $this->assertFieldByName('subject', $subject);
+
+    // Disable privatemsg for recipient 3.
+    db_query('INSERT into {pm_disable} values (%d)', $recipient3->uid);
+
+    $this->assertFalse(privatemsg_get_link(array($recipient3), $author));
+
+    $this->drupalGet(privatemsg_get_link(array($recipient1, $recipient3), $author));
+    $this->assertFieldByName('recipient', $recipient1->name . ' [user]');
+
+    // Disable links to self, verify that a link is only returned when the
+    // author is not the only recipient.
+    variable_set('privatemsg_display_link_self', FALSE);
+
+    $this->assertFalse(privatemsg_get_link(array($author), $author));
+
+    $this->drupalGet(privatemsg_get_link(array($recipient1, $author), $author));
+    $this->assertFieldByName('recipient', $recipient1->name . ' [user]');
+
+    // Verify that link is not shown when recipient doesn't have read
+    // permission.
+    $this->assertFalse(privatemsg_get_link(array($recipient4), $author));
+
+    $this->drupalGet(privatemsg_get_link(array($recipient1, $recipient4), $author));
+    $this->assertFieldByName('recipient', $recipient1->name . ' [user]');
+
+    // Verify that link is not shown when author does not have write permission.
+    $this->drupalLogin($recipient1);
+    $this->assertFalse(privatemsg_get_link(array($author), $recipient1));
+  }
+}
