mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 05:52:25 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			93 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
|    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"
 | |
| 
 | |
| 	pngstructure "github.com/superseriousbusiness/go-png-image-structure/v2"
 | |
| )
 | |
| 
 | |
| 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
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// 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.
 | |
| 	chunks := chunkSlice.Chunks()
 | |
| 	for i, chunk := range chunks {
 | |
| 		if i <= v.lastWrittenChunk {
 | |
| 			// Skip already
 | |
| 			// written chunks.
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		// 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
 | |
| 	}
 | |
| 
 | |
| 	return advance, token, err
 | |
| }
 | |
| 
 | |
| func (v *pngVisitor) writeChunk(chunk *pngstructure.Chunk) error {
 | |
| 	if chunk.Type == pngstructure.EXifChunkType {
 | |
| 		// Replace exif data
 | |
| 		// with zero bytes.
 | |
| 		clear(chunk.Data)
 | |
| 	}
 | |
| 
 | |
| 	// Fix CRC of each chunk.
 | |
| 	chunk.UpdateCrc32()
 | |
| 
 | |
| 	// finally, write chunk to writer.
 | |
| 	_, err := chunk.WriteTo(v.writer)
 | |
| 	return err
 | |
| }
 |