From 452ceb636e37fab2927c688e7b495841879ea29a Mon Sep 17 00:00:00 2001 From: Jeffrey Armstrong Date: Fri, 25 Feb 2022 17:22:43 -0500 Subject: Initial code commit --- pptxzip.f90 | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 pptxzip.f90 (limited to 'pptxzip.f90') diff --git a/pptxzip.f90 b/pptxzip.f90 new file mode 100644 index 0000000..d526125 --- /dev/null +++ b/pptxzip.f90 @@ -0,0 +1,204 @@ +! Copyright (c) 2022 Approximatrix, LLC +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in +! all copies or substantial portions of the Software. +! +! The Software shall be used for Good, not Evil. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +module fpoint_pptxzip +use fpoint_pptxml +implicit none + + private + public::pptxtracted + + type :: pptxtracted + + character(len=2048)::directory + character(len=2048), dimension(:), pointer::slide_paths + character(len=2048), dimension(:), pointer::note_paths + + type(slide), dimension(:), pointer::slides + + contains + + procedure :: open => pptx_open + procedure :: close => pptx_close + procedure :: parse => pptx_parse + procedure :: to_text => pptx_to_text + procedure :: slide_has_notes + procedure :: slide_count + + end type pptxtracted + +contains + + function slide_has_notes(self, i) + implicit none + + class(pptxtracted), intent(in)::self + integer, intent(in)::i + logical::slide_has_notes + + if(i > size(self%note_paths) .or. i < 1) then + slide_has_notes = .false. + else + slide_has_notes = (len_trim(self%note_paths(i)) > 0) + end if + + end function slide_has_notes + + function slide_count(self) + implicit none + + class(pptxtracted), intent(in)::self + integer::slide_count + + if(associated(self%slide_paths)) then + slide_count = size(self%slide_paths) + else + slide_count = 0 + end if + + end function slide_count + + function pptx_open(self, filename) result(res) + use fpoint_fsutil + use m_unzip, only: unzip + implicit none + + logical::res + class(pptxtracted), intent(out)::self + character(len=*), intent(in)::filename + integer::i, slidecount + character(len=2048)::slidedir, slidecheck, notesdir + character(len=4)::numtext + logical::existence + + call get_temporary_directory(self%directory) + i = index(filename, pathsep, back=.true.) + 1 + call append_to_path(self%directory, filename(i:len_trim(filename))//".extracted") + call make_directory(trim(self%directory)) + + ! Extract the file into said directory + res = unzip(filename, trim(self%directory)) + + ! Count slides + slidedir = self%directory + call append_to_path(slidedir, 'ppt') + call append_to_path(slidedir, 'slides') + do i = 1, 512 + slidecheck = slidedir + write(numtext, '(I4)') i + call append_to_path(slidecheck, "slide"//trim(adjustl(numtext))//".xml") + inquire(file=slidecheck, exist=existence) + if(.not. existence) then + exit + end if + end do + slidecount = i - 1 + + allocate(self%slide_paths(slidecount)) + self%slide_paths = slidedir + do i = 1, slidecount + write(numtext, '(I4)') i + call append_to_path(self%slide_paths(i), "slide"//trim(adjustl(numtext))//".xml") + end do + + ! Now check for notes + notesdir = self%directory + call append_to_path(notesdir, 'ppt') + call append_to_path(notesdir, 'notesSlides') + allocate(self%note_paths(slidecount)) + self%note_paths = notesdir + do i = 1, slidecount + write(numtext, '(I4)') i + call append_to_path(self%note_paths(i), "notesSlide"//trim(adjustl(numtext))//".xml") + inquire(file=self%note_paths(i), exist=existence) + if(.not. existence) then + self%note_paths(i) = " " + end if + end do + + ! These should only be explicitly parsed + self%slides => null() + + end function pptx_open + + subroutine pptx_close(self) + implicit none + + class(pptxtracted), intent(inout)::self + + ! Delete directory tree at self%directory + + deallocate(self%slide_paths) + self%slide_paths => null() + + deallocate(self%note_paths) + self%note_paths => null() + + self%directory = " " + + end subroutine pptx_close + + subroutine pptx_parse(self) + use fpoint_pptxml + implicit none + + class(pptxtracted), intent(inout)::self + integer::i + allocate(self%slides(self%slide_count())) + + do i = 1, self%slide_count() + call self%slides(i)%load(self%slide_paths(i)) + end do + + end subroutine pptx_parse + + function pptx_to_text(self) result(t) + use fpoint_pptxml + implicit none + + class(pptxtracted), intent(in)::self + integer::text_length + character(len=:), pointer::t, tmp + integer::i + + t => null() + + if(self%slide_count() > 0 .and. associated(self%slides)) then + text_length = 0 + do i = 1, self%slide_count() + text_length = text_length + self%slides(i)%text_length() + end do + + allocate(character(len=text_length) :: t) + + text_length = 1 + do i = 1, self%slide_count() + tmp => self%slides(i)%to_text() + t(text_length:len(t)) = trim(tmp) + text_length = text_length + len_trim(tmp) + end do + + end if + + end function pptx_to_text + +end module fpoint_pptxzip -- cgit v1.2.3