INFRA-132 - CRM/ - Fix misc oddball syntax
[civicrm-core.git] / CRM / Utils / Zip.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35
36/**
37 * Utilities for working with zip files
38 */
39class CRM_Utils_Zip {
40
41 /**
42 * Given a zip file which contains a single root directory, determine the root's name.
43 *
f4aaa82a
EM
44 * @param ZipArchive $zip
45 *
6a488035
TO
46 * @return mixed; FALSE if #root level items !=1; otherwise, the name of base dir
47 */
48 static public function findBaseDirName(ZipArchive $zip) {
49 $cnt = $zip->numFiles;
50
51 $base = FALSE;
52 $baselen = FALSE;
53
54 for ($i = 0; $i < $cnt; $i++) {
55 $filename = $zip->getNameIndex($i);
56 if ($base === FALSE) {
57 if (preg_match('/^[^\/]+\/$/', $filename) && $filename != './' && $filename != '../') {
58 $base = $filename;
59 $baselen = strlen($filename);
0db6c3e1
TO
60 }
61 else {
6a488035
TO
62 return FALSE;
63 }
d3e86119
TO
64 }
65 elseif (0 != substr_compare($base, $filename, 0, $baselen)) {
6a488035
TO
66 return FALSE;
67 }
68 }
69
70 return $base;
71 }
72
73 /**
74 * Given a zip file, find all directory names in the root
75 *
f4aaa82a
EM
76 * @param ZipArchive $zip
77 *
6a488035
TO
78 * @return array(string), no trailing /
79 */
80 static public function findBaseDirs(ZipArchive $zip) {
81 $cnt = $zip->numFiles;
82 $basedirs = array();
83
84 for ($i = 0; $i < $cnt; $i++) {
85 $filename = $zip->getNameIndex($i);
86 // hypothetically, ./ or ../ would not be legit here
87 if (preg_match('/^[^\/]+\/$/', $filename) && $filename != './' && $filename != '../') {
88 $basedirs[] = rtrim($filename, '/');
89 }
90 }
91
92 return $basedirs;
93 }
94
95 /**
96 * Determine the name of the folder within a zip
97 *
f4aaa82a
EM
98 * @param ZipArchive $zip
99 * @param $expected
100 *
6a488035
TO
101 * @return string or FALSE
102 */
103 static public function guessBasedir(ZipArchive $zip, $expected) {
104 $candidate = FALSE;
105 $basedirs = CRM_Utils_Zip::findBaseDirs($zip);
106 if (in_array($expected, $basedirs)) {
107 $candidate = $expected;
0db6c3e1
TO
108 }
109 elseif (count($basedirs) == 1) {
6a488035
TO
110 $candidate = array_shift($basedirs);
111 }
112 if ($candidate !== FALSE && preg_match('/^[a-zA-Z0-9]/', $candidate)) {
113 return $candidate;
0db6c3e1
TO
114 }
115 else {
6a488035
TO
116 return FALSE;
117 }
118 }
119
120
121 /**
122 * An inefficient helper for creating a ZIP file from data in memory.
123 * This is only intended for building temp files for unit-testing.
124 *
77855840
TO
125 * @param $zipName
126 * String, file name.
127 * @param $dirs
128 * Array, list of directory paths.
129 * @param $files
130 * Array, keys are file names and values are file contents.
6a488035
TO
131 * @return bool
132 */
133 static public function createTestZip($zipName, $dirs, $files) {
134 $zip = new ZipArchive();
135 $res = $zip->open($zipName, ZipArchive::CREATE);
136 if ($res === TRUE) {
137 foreach ($dirs as $dir) {
138 if (!$zip->addEmptyDir($dir)) {
139 return FALSE;
140 }
141 }
142 foreach ($files as $fileName => $fileData) {
143 if (!$zip->addFromString($fileName, $fileData)) {
144 return FALSE;
145 }
146 }
147 $zip->close();
0db6c3e1
TO
148 }
149 else {
e7292422 150 return FALSE;
6a488035
TO
151 }
152 return TRUE;
153 }
154}