...

Source file src/oss.terrastruct.com/d2/lib/pptx/validate.go

Documentation: oss.terrastruct.com/d2/lib/pptx

     1  package pptx
     2  
     3  import (
     4  	"archive/zip"
     5  	"bytes"
     6  	"encoding/xml"
     7  	"fmt"
     8  	"io"
     9  	"strings"
    10  )
    11  
    12  func Validate(pptxContent []byte, nSlides int) error {
    13  	reader := bytes.NewReader(pptxContent)
    14  	zipReader, err := zip.NewReader(reader, reader.Size())
    15  	if err != nil {
    16  		fmt.Printf("error reading pptx content: %v", err)
    17  	}
    18  
    19  	expectedCount := getExpectedPptxFileCount(nSlides)
    20  	if len(zipReader.File) != expectedCount {
    21  		return fmt.Errorf("expected %d files, got %d", expectedCount, len(zipReader.File))
    22  	}
    23  
    24  	for i := 0; i < nSlides; i++ {
    25  		if err := checkFile(zipReader, fmt.Sprintf("ppt/slides/slide%d.xml", i+1)); err != nil {
    26  			return err
    27  		}
    28  		if err := checkFile(zipReader, fmt.Sprintf("ppt/slides/_rels/slide%d.xml.rels", i+1)); err != nil {
    29  			return err
    30  		}
    31  		if err := checkFile(zipReader, fmt.Sprintf("ppt/media/slide%dImage.png", i+1)); err != nil {
    32  			return err
    33  		}
    34  	}
    35  
    36  	for _, file := range zipReader.File {
    37  		if !strings.Contains(file.Name, ".xml") {
    38  			continue
    39  		}
    40  		// checks if the XML content is valid
    41  		f, err := file.Open()
    42  		if err != nil {
    43  			return fmt.Errorf("error opening %s: %v", file.Name, err)
    44  		}
    45  		decoder := xml.NewDecoder(f)
    46  		for {
    47  			if err := decoder.Decode(new(interface{})); err != nil {
    48  				if err == io.EOF {
    49  					break
    50  				}
    51  				return fmt.Errorf("error parsing xml content in %s: %v", file.Name, err)
    52  			}
    53  		}
    54  		defer f.Close()
    55  	}
    56  
    57  	return nil
    58  }
    59  
    60  func checkFile(reader *zip.Reader, fname string) error {
    61  	f, err := reader.Open(fname)
    62  	if err != nil {
    63  		return fmt.Errorf("error opening file %s: %v", fname, err)
    64  	}
    65  	defer f.Close()
    66  	if _, err = f.Stat(); err != nil {
    67  		return fmt.Errorf("error getting file info %s: %v", fname, err)
    68  	}
    69  	return nil
    70  }
    71  
    72  func getExpectedPptxFileCount(nSlides int) int {
    73  	reader := bytes.NewReader(PPTX_TEMPLATE)
    74  	zipReader, err := zip.NewReader(reader, reader.Size())
    75  	if err != nil {
    76  		return -1
    77  	}
    78  	baseFiles := len(zipReader.File)
    79  	presentationFiles := 5    // presentation, rels, app, core, content types
    80  	slideFiles := 3 * nSlides // slides, rels, images
    81  	return baseFiles + presentationFiles + slideFiles
    82  }
    83  

View as plain text