Index: wp-admin/includes/media.php
===================================================================
--- wp-admin/includes/media.php	(revision 20605)
+++ wp-admin/includes/media.php	(working copy)
@@ -145,14 +145,14 @@
 
 	$caption = str_replace( array("\r\n", "\r"), "\n", $caption);
 	$caption = preg_replace_callback( '/<[a-zA-Z0-9]+(?: [^<>]+>)*/', '_cleanup_image_add_caption', $caption );
-	$caption = preg_replace( '/\n+/', '<br />', str_replace('"', '&quot;', $caption) );
+	// convert any remaining line breaks to <br>
+	$caption = preg_replace( '/[ \n\t]*\n[ \t]*/', '<br />', $caption );
 
 	$html = preg_replace( '/(class=["\'][^\'"]*)align(none|left|right|center)\s?/', '$1', $html );
 	if ( empty($align) )
 		$align = 'none';
 
-	$shcode = '[caption id="' . $id . '" align="align' . $align
-	. '" width="' . $width . '" caption="' . $caption . '"]' . $html . '[/caption]';
+	$shcode = '[caption id="' . $id . '" align="align' . $align	. '" width="' . $width . '"]' . $html . $caption . '[/caption]';
 
 	return apply_filters( 'image_add_caption_shortcode', $shcode, $html );
 }
@@ -166,23 +166,10 @@
  */
 function _cleanup_image_add_caption( $matches ) {
 	// remove any line breaks from inside the tags
-	$s = preg_replace( '/[\r\n\t]+/', ' ', $matches[0] );
-	// look for single quotes inside html attributes (for example in title)
-	$s = preg_replace_callback( '/="[^"]+"/', '_cleanup_image_add_caption_callback', $s );
-	return str_replace( '"', "'", $s );
+	return preg_replace( '/[\r\n\t]+/', ' ', $matches[0] );
 }
 
 /**
- * Private preg_replace callback used in _cleanup_image_add_caption()
- *
- * @access private
- * @since 3.4.0
- */
-function _cleanup_image_add_caption_callback( $matches ) {
-	return str_replace( "'", '&#39;', $matches[0] );
-}
-
-/**
  * {@internal Missing Short Description}}
  *
  * @since 2.5.0
@@ -1541,13 +1528,10 @@
 		if ( f.caption.value ) {
 			caption = f.caption.value.replace(/\r\n|\r/g, '\n');
 			caption = caption.replace(/<[a-zA-Z0-9]+( [^<>]+)?>/g, function(a){
-				a = a.replace(/[\r\n\t]+/, ' ').replace(/="[^"]+"/, function(b){
-					return b.replace(/'/g, '&#39;');
-				});
-				return a.replace(/"/g, "'");
+				return a.replace(/[\r\n\t]+/, ' ');
 			});
 
-			caption = caption.replace(/\n+/g, '<br />').replace(/"/g, '&quot;');
+			caption = caption.replace(/\s*\n\s*/g, '<br />');
 		}
 <?php } ?>
 
@@ -1561,7 +1545,7 @@
 		}
 
 		if ( caption )
-			html = '[caption id="" align="'+t.align+'" width="'+t.width+'" caption="'+caption+'"]'+html+'[/caption]';
+			html = '[caption id="" align="'+t.align+'" width="'+t.width+'"]'+html+caption+'[/caption]';
 
 		var win = window.dialogArguments || opener || parent || top;
 		win.send_to_editor(html);
Index: wp-admin/js/editor.dev.js
===================================================================
--- wp-admin/js/editor.dev.js	(revision 20605)
+++ wp-admin/js/editor.dev.js	(working copy)
@@ -73,11 +73,11 @@
 			});
 		}
 
-		// keep <br> tags inside captions
+		// keep <br> tags inside captions and remove line breaks
 		if ( content.indexOf('[caption') != -1 ) {
 			preserve_br = true;
-			content = content.replace(/\[caption[^\]]+\]/g, function(a) {
-				return a.replace(/<br([^>]*)>[\r\n]*/g, '<wp-temp-br$1>');
+			content = content.replace(/\[caption[\s\S]+?\[\/caption\]/g, function(a) {
+				return a.replace(/<br([^>]*)>/g, '<wp-temp-br$1>').replace(/[\r\n\t]+/, '');
 			});
 		}
 
@@ -139,7 +139,8 @@
 	},
 
 	_wp_Autop : function(pee) {
-		var blocklist = 'table|thead|tfoot|tbody|tr|td|th|caption|col|colgroup|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6]|fieldset|legend|hr|noscript|menu|samp|header|footer|article|section|hgroup|nav|aside|details|summary';
+		var preserve_linebreaks = false, preserve_br = false,
+			blocklist = 'table|thead|tfoot|tbody|tr|td|th|caption|col|colgroup|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6]|fieldset|legend|hr|noscript|menu|samp|header|footer|article|section|hgroup|nav|aside|details|summary';
 
 		if ( pee.indexOf('<object') != -1 ) {
 			pee = pee.replace(/<object[\s\S]+?<\/object>/g, function(a){
@@ -153,11 +154,27 @@
 
 		// Protect pre|script tags
 		if ( pee.indexOf('<pre') != -1 || pee.indexOf('<script') != -1 ) {
+			preserve_linebreaks = true;
 			pee = pee.replace(/<(pre|script)[^>]*>[\s\S]+?<\/\1>/g, function(a) {
-				return a.replace(/(\r\n|\n)/g, '<wp_temp_br>');
+				return a.replace(/(\r\n|\n)/g, '<wp-temp-lb>');
 			});
 		}
 
+		// keep <br> tags inside captions and convert line breaks
+		if ( pee.indexOf('[caption') != -1 ) {
+			preserve_br = true;
+			pee = pee.replace(/\[caption[\s\S]+?\[\/caption\]/g, function(a) {
+				// keep existing <br>
+				a = a.replace(/<br([^>]*)>/g, '<wp-temp-br$1>');
+				// no line breaks inside HTML tags
+				a = a.replace(/<[a-zA-Z0-9]+( [^<>]+)?>/g, function(b){
+					return b.replace(/[\r\n\t]+/, ' ');
+				});
+				// convert remaining line breaks to <br>
+				return a.replace(/\s*\n\s*/g, '<wp-temp-br />');
+			});
+		}
+
 		pee = pee + '\n\n';
 		pee = pee.replace(/<br \/>\s*<br \/>/gi, '\n\n');
 		pee = pee.replace(new RegExp('(<(?:'+blocklist+')(?: [^>]*)?>)', 'gi'), '\n$1');
@@ -186,8 +203,12 @@
 		});
 
 		// put back the line breaks in pre|script
-		pee = pee.replace(/<wp_temp_br>/g, '\n');
+		if ( preserve_linebreaks )
+			pee = pee.replace(/<wp-temp-lb>/g, '\n');
 
+		if ( preserve_br )
+			pee = pee.replace(/<wp-temp-br([^>]*)>/g, '<br$1>');
+
 		return pee;
 	},
 
Index: wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin_src.js
===================================================================
--- wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin_src.js	(revision 20605)
+++ wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin_src.js	(working copy)
@@ -139,7 +139,7 @@
 
 		_do_shcode : function(content) {
 			return content.replace(/(?:<p>)?\[(?:wp_)?caption([^\]]+)\]([\s\S]+?)\[\/(?:wp_)?caption\](?:<\/p>)?/g, function(a,b,c){
-				var id, cls, w, cap, div_cls;
+				var id, cls, w, cap, div_cls, img;
 
 				id = b.match(/id=['"]([^'"]*)['"] ?/);
 				b = b.replace(id[0], '');
@@ -150,8 +150,18 @@
 				w = b.match(/width=['"]([0-9]*)['"] ?/);
 				b = b.replace(w[0], '');
 
-				cap = tinymce.trim(b).replace(/caption=['"]/, '').replace(/['"]$/, '');
+				c = tinymce.trim(c);
+				img = c.match(/((?:<a [^>]+>)?<img [^>]+>(?:<\/a>)?)([\s\S]*)/i);
 
+				if ( img && img[2] ) {
+					cap = img[2];
+					img = img[1];
+				} else {
+					// old captions shortcode style
+					cap = tinymce.trim(b).replace(/caption=['"]/, '').replace(/['"]$/, '');
+					img = c;
+				}
+
 				id = ( id && id[1] ) ? id[1] : '';
 				cls = ( cls && cls[1] ) ? cls[1] : 'alignnone';
 				w = ( w && w[1] ) ? w[1] : '';
@@ -164,7 +174,7 @@
 					div_cls += ' mceIEcenter';
 
 				return '<div class="'+div_cls+'"><dl id="'+id+'" class="wp-caption '+cls+'" style="width: '+( 10 + parseInt(w) )+
-				'px"><dt class="wp-caption-dt">'+c+'</dt><dd class="wp-caption-dd">'+cap+'</dd></dl></div>';
+				'px"><dt class="wp-caption-dt">'+img+'</dt><dd class="wp-caption-dd">'+cap+'</dd></dl></div>';
 			});
 		},
 
@@ -187,15 +197,14 @@
 					cls = cls.match(/align[a-z]+/) || 'alignnone';
 
 					cap = cap.replace(/\r\n|\r/g, '\n').replace(/<[a-zA-Z0-9]+( [^<>]+)?>/g, function(a){
-						a = a.replace(/[\r\n\t]+/, ' ').replace(/="[^"]+"/, function(b){
-							return b.replace(/'/g, '&#39;');
-						});
-						return a.replace(/"/g, "'");
+						// no line breaks inside HTML tags
+						return a.replace(/[\r\n\t]+/, ' ');
 					});
 
-					cap = cap.replace(/\n+/g, '<br />').replace(/"/g, '&quot;');
+					// convert remaining line breaks to <br>
+					cap = cap.replace(/\s*\n\s*/g, '<br />');
 
-					return '[caption id="'+id+'" align="'+cls+'" width="'+w+'" caption="'+cap+'"]'+c+'[/caption]';
+					return '[caption id="'+id+'" align="'+cls+'" width="'+w+'"]'+c+cap+'[/caption]';
 				});
 
 				if ( ret.indexOf('[caption') !== 0 ) {
Index: wp-includes/js/tinymce/plugins/wpeditimage/js/editimage.dev.js
===================================================================
--- wp-includes/js/tinymce/plugins/wpeditimage/js/editimage.dev.js	(revision 20605)
+++ wp-includes/js/tinymce/plugins/wpeditimage/js/editimage.dev.js	(working copy)
@@ -419,13 +419,10 @@
 			caption = f.img_cap_text.value;
 
 			caption = caption.replace(/\r\n|\r/g, '\n').replace(/<[a-zA-Z0-9]+( [^<>]+)?>/g, function(a){
-				a = a.replace(/[\r\n\t]+/, ' ').replace(/="[^"]+"/, function(b){
-					return b.replace(/'/g, '&#39;');
-				});
-				return a.replace(/"/g, "'");
+				return a.replace(/[\r\n\t]+/, ' ');
 			});
 
-			caption = caption.replace(/\n+/g, '<br />').replace(/"/g, '&quot;');
+			caption = caption.replace(/\s*\n\s*/g, '<br />');
 
 			if ( DL ) {
 				ed.dom.setAttribs(DL, {
Index: wp-includes/media.php
===================================================================
--- wp-includes/media.php	(revision 20605)
+++ wp-includes/media.php	(working copy)
@@ -724,6 +724,14 @@
  * @return string
  */
 function img_caption_shortcode($attr, $content = null) {
+	// New-style shortcode with the caption inside the shortcode with the link and image tags.
+	if ( ! isset( $attr['caption'] ) ) {
+		preg_match( '#(<a\s.*?<img\s.*?</a>)(.*)#is', $content, $matches ) || preg_match( '#(<img\s.*?>)(.*)#is', $content, $matches );
+		if ( $matches ) {
+			$content = $matches[1];
+			$attr['caption'] = trim( $matches[2] );
+		}
+	}
 
 	// Allow plugins/themes to override the default caption template.
 	$output = apply_filters('img_caption_shortcode', '', $attr, $content);
