| 
									
										
										
										
											2022-01-23 14:41:31 +01:00
										 |  |  | /* | 
					
						
							|  |  |  |    exif-terminator | 
					
						
							|  |  |  |    Copyright (C) 2022 SuperSeriousBusiness admin@gotosocial.org | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |    it under the terms of the GNU Affero General Public License as published by | 
					
						
							|  |  |  |    the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  |    (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |    GNU Affero General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  |    along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package terminator | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"io" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:50:28 +01:00
										 |  |  | 	pngstructure "github.com/superseriousbusiness/go-png-image-structure/v2" | 
					
						
							| 
									
										
										
										
											2022-01-23 14:41:31 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type pngVisitor struct { | 
					
						
							|  |  |  | 	ps               *pngstructure.PngSplitter | 
					
						
							|  |  |  | 	writer           io.Writer | 
					
						
							|  |  |  | 	lastWrittenChunk int | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (v *pngVisitor) split(data []byte, atEOF bool) (int, []byte, error) { | 
					
						
							|  |  |  | 	// execute the ps split function to read in data | 
					
						
							|  |  |  | 	advance, token, err := v.ps.Split(data, atEOF) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return advance, token, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// if we haven't written anything at all yet, then write the png header back into the writer first | 
					
						
							|  |  |  | 	if v.lastWrittenChunk == -1 { | 
					
						
							|  |  |  | 		if _, err := v.writer.Write(pngstructure.PngSignature[:]); err != nil { | 
					
						
							|  |  |  | 			return advance, token, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:50:28 +01:00
										 |  |  | 	// Check if the splitter now has | 
					
						
							|  |  |  | 	// any new chunks in it for us. | 
					
						
							|  |  |  | 	chunkSlice, err := v.ps.Chunks() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return advance, token, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Write each chunk by passing it | 
					
						
							|  |  |  | 	// through our custom write func, | 
					
						
							|  |  |  | 	// which strips out exif and fixes | 
					
						
							|  |  |  | 	// the CRC of each chunk. | 
					
						
							| 
									
										
										
										
											2022-01-23 14:41:31 +01:00
										 |  |  | 	chunks := chunkSlice.Chunks() | 
					
						
							|  |  |  | 	for i, chunk := range chunks { | 
					
						
							| 
									
										
										
										
											2023-11-30 10:50:28 +01:00
										 |  |  | 		if i <= v.lastWrittenChunk { | 
					
						
							|  |  |  | 			// Skip already | 
					
						
							|  |  |  | 			// written chunks. | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2022-01-23 14:41:31 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-11-30 10:50:28 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Write this new chunk. | 
					
						
							|  |  |  | 		if err := v.writeChunk(chunk); err != nil { | 
					
						
							|  |  |  | 			return advance, token, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		v.lastWrittenChunk = i | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Zero data; here you | 
					
						
							|  |  |  | 		// go garbage collector. | 
					
						
							|  |  |  | 		chunk.Data = nil | 
					
						
							| 
									
										
										
										
											2022-01-23 14:41:31 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return advance, token, err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (v *pngVisitor) writeChunk(chunk *pngstructure.Chunk) error { | 
					
						
							|  |  |  | 	if chunk.Type == pngstructure.EXifChunkType { | 
					
						
							| 
									
										
										
										
											2023-11-30 10:50:28 +01:00
										 |  |  | 		// Replace exif data | 
					
						
							|  |  |  | 		// with zero bytes. | 
					
						
							|  |  |  | 		clear(chunk.Data) | 
					
						
							| 
									
										
										
										
											2022-01-23 14:41:31 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:50:28 +01:00
										 |  |  | 	// Fix CRC of each chunk. | 
					
						
							|  |  |  | 	chunk.UpdateCrc32() | 
					
						
							| 
									
										
										
										
											2022-01-23 14:41:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:50:28 +01:00
										 |  |  | 	// finally, write chunk to writer. | 
					
						
							|  |  |  | 	_, err := chunk.WriteTo(v.writer) | 
					
						
							|  |  |  | 	return err | 
					
						
							| 
									
										
										
										
											2022-01-23 14:41:31 +01:00
										 |  |  | } |