--- Postfix.pm.v4594	2007-05-25 15:12:01.000000000 +0200
+++ Postfix.pm	2007-05-25 15:14:46.000000000 +0200
@@ -290,6 +290,10 @@
     my($ORIGFound, $TOFound, $FROMFound, $IPFound, $TIMEFound);
     my($ErrorFound, $ERecordFound, $rectype, $recdata);
     my $InSubject = 0; # Are we adding continuation subject lines?
+    my $OriginalPos = 0; # p record jumpoff point //Glenn
+    my $MaxpRecPos = 0; # Max position where a p record might occur.
+    my @npos = (); # save all p record positions, although we only
+                   # look at/use the first and last.
 
     #print STDERR "In ReadQf\n";
     #$message->{store}->print();
@@ -299,6 +303,10 @@
     # Just in case we get a message with no headers at all
     @{$message->{headers}} = ();
 
+    # seek to end of file and save position, to make sure p records don't
+    # try go past this point. 17 is the record size for a p record.
+    seek $RQf, -17, 2;
+    $MaxpRecPos = tell $RQf;
 
     # Seek to the start of the file in case anyone read the file
     # between me opening it and locking it.
@@ -389,6 +397,56 @@
         $message->{postfixrecips}{lc("$recdata")} = 1;
         $TOFound = 1;
         #print STDERR "Pre O Recip $recdata\n";
+      } elsif ($rectype eq 'p') {
+	# //Glenn 2007-01-16
+	# Handle p records (GOTO like in-place edit thing) by reading
+	# the pointed to data into the main message object, and
+	# silently discarding the actual p record.
+	# This p record should only point to added recipients, or
+	# moved records of the same type already handled in this
+	# segment, so lets just store the jumpoff point and loop.
+	# When we hit the next p record it should be the "jump back to
+        # original pos" one, or another forward p record... so we'll
+	# check that and act accordingly..
+	next if ($recdata+0 == 0); # Ignore zero (placeholder) jumps
+	if ($recdata+0 > $MaxpRecPos) {
+	    MailScanner::Log::WarnLog("p record handling: Attempt to jump beyond end of file, aborting file.");
+	    $ErrorFound = 1;
+	    last;
+	}
+	push @npos, $recdata+0; # save jumpto position, for loop detection.
+	if ($OriginalPos == 0) {
+	   # Jump to after E record and commence
+	   $OriginalPos = tell $RQf;
+	   seek $RQf, $recdata+0, 0; # jump. we should check this works.
+	   next;
+	} else {
+	  # We're at the return point, or moving even furtehr away...
+	  if ($recdata+0 < $OriginalPos) {
+	     # Error exit, carp or whatever. Probably should do the
+	     # nice exit Jules does above. For now, warn and use
+	     # OriginalPos
+	     MailScanner::Log::WarnLog("p record handling: $recdata < $OriginalPos, using $OriginalPos instead!");
+	     seek $RQf, $OriginalPos, 0; # jump back up. we should chk this.
+	     $OriginalPos = 0; # We're home again... Reset to prepare for
+			       # any new warps
+	     @npos = ();
+	  } else {
+	    seek $RQf, $recdata+0, 0; # jump back or forward. we should chk this works.
+	    if ($recdata+0 < $npos[$#npos-1]) {
+	       if ($recdata+0 >= $npos[0]) {
+		  MailScanner::Log::WarnLog("p record handling: Loop condition found, aborting file.");
+		  $ErrorFound = 1;
+		  $OriginalPos = 0; # Reset to not fool next segment loop
+	          @npos = ();
+		  last;
+	       }
+	       $OriginalPos = 0; # We're home again... Reset to prepare for
+		                 # any new warps
+	       @npos = ();
+	    }
+	  }
+	}
       } else {
         # Some other record type. Just store it and move on.
         push @{$message->{metadata}}, "$rectype$recdata";
@@ -407,6 +465,58 @@
         last;
       }
       last if $rectype eq 'N' && $recdata eq "";
+      if ($rectype eq 'p') {
+	 # //Glenn 2007-01-16
+	 # Handle p records (GOTO like in-place edit thing) by reading
+	 # the pointed to data into the main message object, and
+	 # silently discarding the actual p record.
+	 # This p record should only point to added headers, or
+	 # moved records of the same type already handled in this
+	 # segment, so lets just store the jumpoff point and loop.
+	 # When we hit the next p record it should be the "jump back to
+         # original pos" one, or another forward p record... so we'll
+	 # check that and act accordingly..
+	 next if ($recdata+0 == 0); # Ignore zero (placeholder) jumps
+	 if ($recdata+0 > $MaxpRecPos) {
+	    MailScanner::Log::WarnLog("p record handling: Attempt to jump beyond end of file, aborting file.");
+	    $ErrorFound = 1;
+	    last;
+	 }
+	 push @npos, $recdata+0; # save jumpto position, for loop detection.
+	 if ($OriginalPos == 0) {
+	    # Jump to after E record and commence
+	    $OriginalPos = tell $RQf;
+	    seek $RQf, $recdata+0, 0; # jump. we should check this works.
+#	    next;
+	 } else {
+	   # We're at the return point, or moving even furtehr away...
+	   if ($recdata+0 < $OriginalPos) {
+	      # Error exit, carp or whatever. Probably should do the
+	      # nice exit Jules does above. For now, warn and use
+	      # OriginalPos
+	      MailScanner::Log::WarnLog("p record handling: $recdata < $OriginalPos, using $OriginalPos instead!");
+	      seek $RQf, $OriginalPos, 0; # jump back up. we should chk this.
+	      $OriginalPos = 0; # We're home again... Reset to prepare for
+			        # any new warps
+	      @npos = ();
+	   } else {
+	     seek $RQf, $recdata+0, 0; # jump back or forward. we should chk this works.
+	     if ($recdata+0 < $npos[$#npos-1]) {
+	        if ($recdata+0 >= $npos[0]) {
+        	   MailScanner::Log::WarnLog("p record handling: Loop condition found, aborting file.");
+		   $ErrorFound = 1;
+	           $OriginalPos = 0; # Reset to not fool next segment loop...
+	           @npos = ();
+		   last;
+	        }
+	        $OriginalPos = 0; # We're home again... Reset to prepare for
+		                  # any new warps
+	        @npos = ();
+	     }
+	   }
+	 }
+	 next; # done, don't add a spurious "converted p to N" record.
+      }
       push @{$message->{headers}}, $recdata; # Headers have no leading N
       if ($recdata =~ /^Subject:\s*(\S.*)?$/i) {
         $message->{subject} = $1;
@@ -441,7 +551,70 @@
 
     # We are now at the end of the headers. Jump straight to the metadata
     # after the message.
-    seek $RQf, $MsgContSize+$DataOffset, 0;
+#    seek $RQf, $MsgContSize+$DataOffset, 0;
+
+# Inelegant, but working. Instead of an efficient seek, we spinn through to
+# after X record.
+    while(($rectype, $recdata) = ReadRecord($RQf)) {
+      #print STDERR "Metadata type $rectype data \"$recdata\"\n";
+      if ($rectype eq 'X') {
+        last;
+      }
+      if ($rectype eq 'p') {
+	# //Glenn 2007-01-16
+	# Handle p records (GOTO like in-place edit thing) by reading
+	# the pointed to data into the main message object, and
+	# silently discarding the actual p record.
+	# This p record should only point to a new body record, or
+	# moved records of the same type already handled in this
+	# segment, so lets just store the jumpoff point and loop.
+	# When we hit the next p record it should be the "jump back to
+        # original pos" one, or another forward p record... so we'll
+	# check that and act accordingly..
+	next if ($recdata+0 == 0); # Ignore zero (placeholder) jumps
+	if ($recdata+0 > $MaxpRecPos) {
+	    MailScanner::Log::WarnLog("p record handling: Attempt to jump beyond end of file, aborting file.");
+	    $ErrorFound = 1;
+	    last;
+	}
+	push @npos, $recdata+0; # save jumpto position, for loop detection.
+	if ($OriginalPos == 0) {
+	   # Jump to after E record and commence
+	   $OriginalPos = tell $RQf;
+	   seek $RQf, $recdata+0, 0; # jump. we should check this works.
+	   next;
+	} else {
+	  # We're at the return point, or moving even furtehr away...
+	  if ($recdata+0 < $OriginalPos) {
+	     # Error exit, carp or whatever. Probably should do the
+	     # nice exit Jules does above. For now, warn and use
+	     # OriginalPos
+	     MailScanner::Log::WarnLog("p record handling: $recdata < $OriginalPos, using $OriginalPos instead!");
+	     seek $RQf, $OriginalPos, 0; # jump back up. we should chk this.
+	     $OriginalPos = 0; # We're home again... Reset to prepare for
+			       # any mew warps
+	     @npos = ();
+	  } else {
+	    seek $RQf, $recdata+0, 0; # jump back or forward. we should chk this works.
+	    if ($recdata+0 < $npos[$#npos-1]) {
+	       if ($recdata+0 >= $npos[0]) {
+		  MailScanner::Log::WarnLog("p record handling: Loop condition found, aborting file.");
+		  $ErrorFound = 1;
+		  $OriginalPos = 0; # Reset to not fool next segment loop...
+		  last;
+	       }
+	       $OriginalPos = 0; # We're home again... Reset to prepare for
+		                 # any mew warps
+	       @npos = ();
+	    }
+	  }
+	}
+      }
+    }
+    # "safety" seek, in case things go badly above. We also need to return "before" the X record, so that it is copied over below.
+    #my $CurrentPos = tell $RQf;
+    #print STDERR "MsgContSize+DataOffset = ",$MsgContSize+$DataOffset,"\nCuurentPos = ",$CurrentPos+0,"\n";
+    seek $RQf, $MsgContSize+$DataOffset, 0; # if ($MsgContSize+$DataOffset ne $CurrentPos+0);
 
     # We are now in the metadata after the message.
     #print STDERR "Reading post data\n";
@@ -485,6 +658,57 @@
         $message->{postfixrecips}{"$recdata"} = 1;
         $TOFound = 1;
         #print STDERR "Post O Recip $recdata\n";
+      } elsif ($rectype eq 'p') {
+	# //Glenn 2007-01-16
+	# Handle p records (GOTO like in-place edit thing) by reading
+	# the pointed to data into the main message object, and
+	# silently discarding the actual p record.
+	# This p record should only point to added recipients, or
+	# moved records of the same type already handled in this
+	# segment, so lets just store the jumpoff point and loop.
+	# When we hit the next p record it should be the "jump back to
+        # original pos" one, or another forward p record... so we'll
+	# check that and act accordingly..
+	# I'm not sure this segment can have p records, but better
+	# safe than sorry.
+	next if ($recdata+0 == 0); # Ignore zero (placeholder) jumps
+	if ($recdata+0 > $MaxpRecPos) {
+	    MailScanner::Log::WarnLog("p record handling: Attempt to jump beyond end of file, aborting file.");
+	    $ErrorFound = 1;
+	    last;
+	}
+	push @npos, $recdata+0; # save jumpto position, for loop detection.
+	if ($OriginalPos == 0) {
+	   # Jump to after E record and commence
+	   $OriginalPos = tell $RQf;
+	   seek $RQf, $recdata+0, 0; # jump. we should check this works.
+	   next;
+	} else {
+	  # We're at the return point, or moving even furtehr away...
+	  if ($recdata+0 < $OriginalPos) {
+	     # Error exit, carp or whatever. Probably should do the
+	     # nice exit Jules does above. For now, warn and use
+	     # OriginalPos
+	     MailScanner::Log::WarnLog("p record handling: $recdata < $OriginalPos, using $OriginalPos instead!");
+	     seek $RQf, $OriginalPos, 0; # jump back up. we should chk this.
+	     $OriginalPos = 0; # We're home again... Reset to prepare for
+			       # any mew warps
+	     @npos = ();
+	  } else {
+	    seek $RQf, $recdata+0, 0; # jump back or forward. we should chk this works.
+	    if ($recdata+0 < $npos[$#npos-1]) {
+	       if ($recdata+0 >= $npos[0]) {
+		  MailScanner::Log::WarnLog("p record handling: Loop condition found, aborting file.");
+		  $ErrorFound = 1;
+		  # no need to reset $OriginalPos since this is the last segment.
+		  last;
+	       }
+	       $OriginalPos = 0; # We're home again... Reset to prepare for
+		                 # any mew warps
+	       @npos = ();
+	    }
+	  }
+	}
       } else {
         # Some other record type. Just store it and move on.
         push @{$message->{metadata}}, "$rectype$recdata";