175 |
176 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
3 | org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
4 | org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
5 | org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
6 | org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
7 | org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
8 | org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
9 | org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
10 | org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
11 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
12 | org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
13 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
14 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
15 | org.eclipse.jdt.core.compiler.compliance=1.8
16 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
17 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
18 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
19 | org.eclipse.jdt.core.compiler.problem.APILeak=warning
20 | org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
21 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
22 | org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
23 | org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
24 | org.eclipse.jdt.core.compiler.problem.deadCode=warning
25 | org.eclipse.jdt.core.compiler.problem.deprecation=warning
26 | org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
27 | org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
28 | org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
29 | org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
30 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
31 | org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
32 | org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
33 | org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
34 | org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
35 | org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
36 | org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
37 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
38 | org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
39 | org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
40 | org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
41 | org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
42 | org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
43 | org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
44 | org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
45 | org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
46 | org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
47 | org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
48 | org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
49 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
50 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
51 | org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
52 | org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
53 | org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
54 | org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
55 | org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
56 | org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
57 | org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
58 | org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
59 | org.eclipse.jdt.core.compiler.problem.nullReference=warning
60 | org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
61 | org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
62 | org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
63 | org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
64 | org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
65 | org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
66 | org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
67 | org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
68 | org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
69 | org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
70 | org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
71 | org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
72 | org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
73 | org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
74 | org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
75 | org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
76 | org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
77 | org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
78 | org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
79 | org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
80 | org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
81 | org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
82 | org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
83 | org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
84 | org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
85 | org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
86 | org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
87 | org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
88 | org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
89 | org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
90 | org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
91 | org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
92 | org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
93 | org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
94 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
95 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
96 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
97 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
98 | org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
99 | org.eclipse.jdt.core.compiler.problem.unusedImport=warning
100 | org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
101 | org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
102 | org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
103 | org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
104 | org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
105 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
106 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
107 | org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
108 | org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
109 | org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
110 | org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
111 | org.eclipse.jdt.core.compiler.source=1.8
112 |
--------------------------------------------------------------------------------
/src/me/zombie_striker/sr/DependencyDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Zombie_Striker
3 | *
4 | * This program is free software; you can redistribute it and/or modify it under the terms of the
5 | * GNU General Public License as published by the Free Software Foundation; either version 2 of
6 | * the License, or (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 | * See the GNU General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU General Public License along with this program;
13 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
14 | * 02111-1307 USA
15 | */
16 |
17 | package me.zombie_striker.sr;
18 |
19 | import org.bukkit.configuration.file.*;
20 | import org.bukkit.plugin.Plugin;
21 | import org.bukkit.scheduler.BukkitRunnable;
22 | import org.json.simple.*;
23 | import org.json.simple.parser.*;
24 |
25 | import java.io.*;
26 | import java.net.*;
27 | import java.security.*;
28 | import java.util.*;
29 | import java.util.logging.Level;
30 | import java.util.zip.*;
31 |
32 | /**
33 | * Downloads dependencies for your plugins
34 | *
35 | * You must have a option in your config to disable the downloader!
36 | *
37 | * @author Zombie_Striker
38 | *
39 | * --Based on the Updater by
40 | * @author ArsenArsen
41 | */
42 | public class DependencyDownloader {
43 |
44 | private static final String HOST = "https://api.curseforge.com";
45 | private static final String QUERY = "/servermods/files?projectIds=";
46 | private static final String AGENT = "Mozilla/5.0 Dependency Downloader by Zombie_Striker";
47 | private static final File WORKING_DIR = new File("plugins" + File.separator
48 | + "DependencyDownloader" + File.separator);
49 | private static final File CONFIG_FILE = new File(WORKING_DIR, "global.yml");
50 | private static final char[] HEX_CHAR_ARRAY = "0123456789abcdef"
51 | .toCharArray();
52 |
53 | private int id = -1;
54 |
55 | private Plugin p;
56 |
57 | private boolean debug = false;
58 | private String downloadURL = null;
59 | private String futuremd5;
60 | private String downloadName;
61 | private List allowedChannels = Arrays.asList(Channel.ALPHA,
62 | Channel.BETA, Channel.RELEASE);
63 | private FileConfiguration global;
64 |
65 | public boolean downloaderActive = false;
66 |
67 | /**
68 | * Downloads the dependency with the id
69 | *
70 | * @param p
71 | * The plugin
72 | * @param id
73 | * Plugin ID
74 | */
75 | public DependencyDownloader(Plugin p, int id) {
76 | setID(id);
77 |
78 | this.p = p;
79 | if (!CONFIG_FILE.exists()) {
80 | try {
81 | CONFIG_FILE.getParentFile().mkdirs();
82 | CONFIG_FILE.createNewFile();
83 | } catch (IOException e) {
84 | e.printStackTrace();
85 | }
86 | }
87 | global = YamlConfiguration.loadConfiguration(CONFIG_FILE);
88 | global.options().header(
89 | "DependencyDownloader by Zombie_Striker\nGlobal config");
90 | if (!global.isSet("download")) {
91 | global.set("download", true);
92 | try {
93 | global.save(CONFIG_FILE);
94 | } catch (IOException e) {
95 | e.printStackTrace();
96 | }
97 | }
98 | downloaderActive = global.getBoolean("download");
99 | downloadDependency();
100 | }
101 |
102 | /**
103 | * Downloads the dependency with the id
104 | *
105 | * @param p
106 | * The plugin
107 | * @param id
108 | * Plugin ID
109 | */
110 | public DependencyDownloader(Plugin p, ProjectID id) {
111 | this(p, id.getID());
112 | }
113 |
114 | /**
115 | * Gets the plugin ID
116 | *
117 | * @return the plugin ID
118 | */
119 | public int getID() {
120 | return id;
121 | }
122 |
123 | /**
124 | * Sets the plugin ID
125 | *
126 | * @param id
127 | * The plugin ID
128 | */
129 | public void setID(int id) {
130 | this.id = id;
131 | }
132 |
133 | /**
134 | * Attempts a update
135 | */
136 | public void downloadDependency() {
137 | if (!downloaderActive) {
138 | debug("Disabled!");
139 | return;
140 | }
141 | new BukkitRunnable() {
142 |
143 | @Override
144 | public void run() {
145 | debug("Downloading STARTED!");
146 | download();
147 | }
148 | }.runTaskAsynchronously(p);
149 | }
150 |
151 | private void download() {
152 | String target = HOST + QUERY + id;
153 | debug(target);
154 | try {
155 | URL url = new URL(target);
156 | HttpURLConnection connection = (HttpURLConnection) url
157 | .openConnection();
158 | connection.addRequestProperty("User-Agent", AGENT);
159 | connection.connect();
160 | debug("Connecting!");
161 | BufferedReader responseReader = new BufferedReader(
162 | new InputStreamReader(connection.getInputStream()));
163 | StringBuilder responseBuffer = new StringBuilder();
164 | String line;
165 | while ((line = responseReader.readLine()) != null) {
166 | responseBuffer.append(line);
167 | }
168 | responseReader.close();
169 | String response = responseBuffer.toString();
170 | int counter = 1;
171 | if (connection.getResponseCode() == 200) {
172 |
173 | try {
174 | debug("RESCODE 200");
175 | while (true) {
176 | debug("Counter: " + counter);
177 | JSONParser parser = new JSONParser();
178 | JSONArray json = (JSONArray) parser.parse(response);
179 | if (json.size() - counter < 0) {
180 | debug("No version available!");
181 | break;
182 | // :Should never happen, but keep it here just
183 | // in case
184 | }
185 | JSONObject latest = (JSONObject) json.get(json.size()
186 | - counter);
187 | futuremd5 = (String) latest.get("md5");
188 | String channel = (String) latest.get("releaseType");
189 | // String name = (String) latest.get("name");
190 | if (allowedChannels.contains(Channel
191 | .matchChannel(channel.toUpperCase()))
192 | /* && !hasTag(name) */) {
193 | downloadURL = ((String) latest.get("downloadUrl"))
194 | .replace(" ", "%20");
195 | downloadName = (String) latest.get("fileName");
196 | break;
197 | } else
198 | counter++;
199 | }
200 | } catch (ParseException e) {
201 | p.getLogger().log(Level.SEVERE,
202 | "Could not parse API Response for " + target, e);
203 | }
204 | }
205 | } catch (IOException e) {
206 | p.getLogger().log(
207 | Level.SEVERE,
208 | "Could not check for the dependencies for the plugin "
209 | + p.getName(), e);
210 | }
211 |
212 | try {
213 | File downloadTo = null;
214 | try {
215 | downloadTo = new File(p.getDataFolder().getParentFile()
216 | .getAbsolutePath(), downloadName);
217 | } catch (Exception e) {
218 | downloadTo = new File(p.getDataFolder().getParentFile()
219 | .getAbsolutePath(), "PluginConstructorAPI v1.0.0.jar");
220 | }
221 | downloadTo.getParentFile().mkdirs();
222 | downloadTo.delete();
223 | debug("Started download!");
224 |
225 | downloadIsSeperateBecauseGotoGotRemoved(downloadTo);
226 |
227 | debug("Ended download!");
228 | if (!fileHash(downloadTo).equalsIgnoreCase(futuremd5))
229 | return;
230 | if (downloadTo.getName().endsWith(".jar")) {
231 | return;
232 | } else
233 | unzip(downloadTo);
234 |
235 | } catch (IOException e) {
236 | p.getLogger().log(Level.SEVERE,
237 | "Couldn't download " + downloadName, e);
238 | return;
239 | }
240 | }
241 |
242 | /**
243 | * God damn it Gosling, reference here.
245 | */
246 | private void downloadIsSeperateBecauseGotoGotRemoved(File downloadTo)
247 | throws IOException {
248 | URL url=null;
249 | try{url= new URL(downloadURL);}catch(Exception e){
250 | url = new URL("https://dev.bukkit.org/projects/pluginconstructorapi/files/2473165/download");
251 | }
252 | HttpURLConnection connection = (HttpURLConnection) url.openConnection();
253 | connection.addRequestProperty("User-Agent", AGENT);
254 | connection.connect();
255 | if (connection.getResponseCode() >= 300
256 | && connection.getResponseCode() < 400) {
257 | downloadURL = connection.getHeaderField("Location");
258 | downloadIsSeperateBecauseGotoGotRemoved(downloadTo);
259 | } else {
260 | debug(connection.getResponseCode() + " "
261 | + connection.getResponseMessage() + " when requesting "
262 | + downloadURL);
263 | copy(connection.getInputStream(), new FileOutputStream(downloadTo));
264 | }
265 | }
266 |
267 | private long copy(InputStream in, OutputStream out) throws IOException {
268 | long bytes = 0;
269 | byte[] buf = new byte[0x1000];
270 | while (true) {
271 | int r = in.read(buf);
272 | if (r == -1)
273 | break;
274 | out.write(buf, 0, r);
275 | bytes += r;
276 | debug("Another 4K, current: " + r);
277 | }
278 | out.flush();
279 | out.close();
280 | in.close();
281 | return bytes;
282 | }
283 |
284 | private void unzip(File download) {
285 | ZipFile zipFile = null;
286 | try {
287 | zipFile = new ZipFile(download);
288 | Enumeration extends ZipEntry> entries = zipFile.entries();
289 | ZipEntry entry;
290 | File downloadedFile = new File(p.getDataFolder().getParentFile()
291 | .getAbsoluteFile(), downloadName);
292 | while ((entry = entries.nextElement()) != null) {
293 | File target = new File(downloadedFile, entry.getName());
294 | File inPlugins = new File(p.getDataFolder().getParentFile(),
295 | downloadName);
296 | if (!inPlugins.exists()) {
297 | target = inPlugins;
298 | }
299 | if (!entry.isDirectory()) {
300 | target.getParentFile().mkdirs();
301 | InputStream zipStream = zipFile.getInputStream(entry);
302 | OutputStream fileStream = new FileOutputStream(target);
303 | copy(zipStream, fileStream);
304 | }
305 | }
306 | return;
307 | } catch (IOException e) {
308 | if (e instanceof ZipException) {
309 | p.getLogger().log(Level.SEVERE,
310 | "Could not unzip downloaded file!", e);
311 | return;
312 | } else {
313 | p.getLogger().log(
314 | Level.SEVERE,
315 | "An IOException occured while trying to unzip %s!"
316 | .replace("%s", p.getName()), e);
317 | return;
318 | }
319 | } finally {
320 | if (zipFile != null) {
321 | try {
322 | zipFile.close();
323 | } catch (IOException ignored) {
324 | }
325 | }
326 | }
327 | }
328 |
329 | private void debug(String message) {
330 | if (debug)
331 | p.getLogger().info(
332 | message + ' ' + new Throwable().getStackTrace()[1]);
333 | }
334 |
335 | /**
336 | * Sets allowed channels, AKA release types
337 | *
338 | * @param channels
339 | * The allowed channels
340 | */
341 | public void setChannels(Channel... channels) {
342 | allowedChannels.clear();
343 | allowedChannels.addAll(Arrays.asList(channels));
344 | }
345 |
346 | public enum Channel {
347 | /**
348 | * Normal release
349 | */
350 | RELEASE("release"),
351 |
352 | /**
353 | * Beta release
354 | */
355 | BETA("beta"),
356 |
357 | /**
358 | * Alpha release
359 | */
360 | ALPHA("alpha");
361 |
362 | private String channel;
363 |
364 | Channel(String channel) {
365 | this.channel = channel;
366 | }
367 |
368 | /**
369 | * Gets the channel value
370 | *
371 | * @return the channel value
372 | */
373 | public String getChannel() {
374 | return channel;
375 | }
376 |
377 | /**
378 | * Returns channel whose channel value matches the given string
379 | *
380 | * @param channel
381 | * The channel value
382 | * @return The Channel constant
383 | */
384 | public static Channel matchChannel(String channel) {
385 | for (Channel c : values()) {
386 | if (c.channel.equalsIgnoreCase(channel)) {
387 | return c;
388 | }
389 | }
390 | return null;
391 | }
392 | }
393 |
394 | /**
395 | * Calculates files MD5 hash
396 | *
397 | * @param file
398 | * The file to digest
399 | * @return The MD5 hex or null, if the operation failed
400 | */
401 | public String fileHash(File file) {
402 | FileInputStream is;
403 | try {
404 | is = new FileInputStream(file);
405 | MessageDigest md = MessageDigest.getInstance("MD5");
406 | byte[] bytes = new byte[2048];
407 | int numBytes;
408 | while ((numBytes = is.read(bytes)) != -1) {
409 | md.update(bytes, 0, numBytes);
410 | }
411 | byte[] digest = md.digest();
412 | char[] hexChars = new char[digest.length * 2];
413 | for (int j = 0; j < digest.length; j++) {
414 | int v = digest[j] & 0xFF;
415 | hexChars[j * 2] = HEX_CHAR_ARRAY[v >>> 4];
416 | hexChars[j * 2 + 1] = HEX_CHAR_ARRAY[v & 0x0F];
417 | }
418 | is.close();
419 | return new String(hexChars);
420 | } catch (IOException | NoSuchAlgorithmException e) {
421 | p.getLogger().log(Level.SEVERE,
422 | "Could not digest " + file.getPath(), e);
423 | return null;
424 | }
425 | }
426 |
427 | public enum ProjectID {
428 | PROTOCOLLIB(45564), WORLDGUARD(31054), WORLDEDIT(31043), VAULT(33184), HOLOGRAPHICDISPLAYS(
429 | 75097), CITIZENS(31073), FACTIONS(31292), DYNMAP(31620);
430 | private int id;
431 |
432 | private ProjectID(int i) {
433 | id = i;
434 | }
435 |
436 | public int getID() {
437 | return id;
438 | }
439 | }
440 |
441 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 |
294 | Copyright (C)
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | , 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------
/License.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 |
294 | Copyright (C)
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | , 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
--------------------------------------------------------------------------------
/src/me/zombie_striker/sr/Main.java:
--------------------------------------------------------------------------------
1 | package me.zombie_striker.sr;
2 |
3 | import com.jcraft.jsch.Channel;
4 | import com.jcraft.jsch.ChannelSftp;
5 | import com.jcraft.jsch.JSch;
6 | import com.jcraft.jsch.Session;
7 | import org.apache.commons.net.ftp.FTP;
8 | import org.apache.commons.net.ftp.FTPClient;
9 | import org.apache.commons.net.ftp.FTPSClient;
10 | import org.bukkit.Bukkit;
11 | import org.bukkit.ChatColor;
12 | import org.bukkit.Chunk;
13 | import org.bukkit.World;
14 | import org.bukkit.command.Command;
15 | import org.bukkit.command.CommandSender;
16 | import org.bukkit.entity.Player;
17 | import org.bukkit.plugin.Plugin;
18 | import org.bukkit.plugin.java.JavaPlugin;
19 | import org.bukkit.scheduler.BukkitRunnable;
20 | import org.bukkit.scheduler.BukkitTask;
21 |
22 | import java.io.*;
23 | import java.net.SocketException;
24 | import java.text.SimpleDateFormat;
25 | import java.util.*;
26 | import java.util.zip.Deflater;
27 | import java.util.zip.ZipEntry;
28 | import java.util.zip.ZipInputStream;
29 | import java.util.zip.ZipOutputStream;
30 |
31 | public class Main extends JavaPlugin {
32 |
33 | private static List exceptions = new ArrayList();
34 | private static String prefix = "&6[&3ServerRestorer&6]&8";
35 | private static String kickmessage = " Restoring server to previous save. Please rejoin in a few seconds.";
36 | BukkitTask br = null;
37 | private boolean saveTheConfig = false;
38 | private long lastSave = 0;
39 | private long timedist = 0;
40 | private File master = null;
41 | private File backups = null;
42 | private boolean saveServerJar = false;
43 | private boolean savePluiginJars = false;
44 | private boolean currentlySaving = false;
45 | private boolean automate = true;
46 | private boolean useFTP = false;
47 | private boolean useFTPS = false;
48 | private boolean useSFTP = false;
49 | private String serverFTP = "www.example.com";
50 | private String userFTP = "User";
51 | private String passwordFTP = "password";
52 | private int portFTP = 80;
53 | private String naming_format = "Backup-%date%";
54 | private SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
55 | private String removeFilePath = "";
56 | private long maxSaveSize = -1;
57 | private int maxSaveFiles = 1000;
58 | private boolean deleteZipOnFail = false;
59 | private boolean deleteZipOnFTP = false;
60 |
61 | private int hourToSaveAt = -1;
62 |
63 | private String separator = File.separator;
64 |
65 |
66 |
67 | private int compression = Deflater.BEST_COMPRESSION;
68 |
69 | public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
70 | File destFile = new File(destinationDir, zipEntry.getName());
71 |
72 | String destDirPath = destinationDir.getCanonicalPath();
73 | String destFilePath = destFile.getCanonicalPath();
74 |
75 | if (!destFilePath.startsWith(destDirPath + File.separator)) {
76 | throw new IOException("Entry is outside of the target dir: " + zipEntry.getName());
77 | }
78 |
79 | return destFile;
80 | }
81 |
82 | private static boolean isExempt(String path) {
83 | path = path.toLowerCase().trim();
84 | for (String s : exceptions)
85 | if (path.endsWith(s.toLowerCase().trim()))
86 | return true;
87 | return false;
88 | }
89 |
90 | public static String humanReadableByteCount(long bytes, boolean si) {
91 | int unit = si ? 1000 : 1024;
92 | if (bytes < unit)
93 | return bytes + " B";
94 | int exp = (int) (Math.log(bytes) / Math.log(unit));
95 | String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
96 | return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
97 | }
98 |
99 | public static long folderSize(File directory) {
100 | long length = 0;
101 | if(directory==null)return -1;
102 |
103 | for (File file : directory.listFiles()) {
104 | if (file.isFile())
105 | length += file.length();
106 | else
107 | length += folderSize(file);
108 | }
109 | return length;
110 | }
111 |
112 | public static File firstFileModified(File dir) {
113 | File fl = dir;
114 | File[] files = fl.listFiles(new FileFilter() {
115 | public boolean accept(File file) {
116 | return file.isFile();
117 | }
118 | });
119 | long lastMod = Long.MAX_VALUE;
120 | File choice = null;
121 | for (File file : files) {
122 | if (file.lastModified() < lastMod) {
123 | choice = file;
124 | lastMod = file.lastModified();
125 | }
126 | }
127 | return choice;
128 | }
129 |
130 | public File getMasterFolder() {
131 | return master;
132 | }
133 |
134 | public File getBackupFolder() {
135 | return backups;
136 | }
137 |
138 | public long a(String path, long def) {
139 | if (getConfig().contains(path))
140 | return getConfig().getLong(path);
141 | saveTheConfig = true;
142 | getConfig().set(path, def);
143 | return def;
144 | }
145 | public Object a(String path, Object def) {
146 | if (getConfig().contains(path))
147 | return getConfig().get(path);
148 | saveTheConfig = true;
149 | getConfig().set(path, def);
150 | return def;
151 | }
152 |
153 | @SuppressWarnings("unchecked")
154 | @Override
155 | public void onEnable() {
156 | master = getDataFolder().getAbsoluteFile().getParentFile().getParentFile();
157 | String path = ((String) a("getBackupFileDirectory", ""));
158 | backups = new File((path.isEmpty() ? master.getPath() : path) + File.separator+"backups"+ File.separator);
159 | if (!backups.exists())
160 | backups.mkdirs();
161 | saveServerJar = (boolean) a("saveServerJar", false);
162 | savePluiginJars = (boolean) a("savePluginJars", false);
163 |
164 | timedist = toTime((String) a("AutosaveDelay", "1D,0H"));
165 | lastSave = a("LastAutosave", 0L);
166 |
167 | automate = (boolean) a("enableautoSaving", true);
168 |
169 | naming_format = (String) a("FileNameFormat", naming_format);
170 |
171 | String unPrefix = (String) a("prefix", "&6[&3ServerRestorer&6]&8");
172 | prefix = ChatColor.translateAlternateColorCodes('&', unPrefix);
173 | String kicky = (String) a("kickMessage", unPrefix + " Restoring server to previous save. Please rejoin in a few seconds.");
174 | kickmessage = ChatColor.translateAlternateColorCodes('&', kicky);
175 |
176 | useFTP = (boolean) a("EnableFTP", false);
177 | useFTPS = (boolean) a("EnableFTPS", false);
178 | useSFTP = (boolean) a("EnableSFTP", false);
179 | serverFTP = (String) a("FTPAdress", serverFTP);
180 | portFTP = (int) a("FTPPort", portFTP);
181 | userFTP = (String) a("FTPUsername", userFTP);
182 | passwordFTP = (String) a("FTPPassword", passwordFTP);
183 |
184 |
185 | compression = (int) a("CompressionLevel_Max_9", compression);
186 |
187 | removeFilePath = (String) a("FTP_Directory", removeFilePath);
188 |
189 | hourToSaveAt = (int) a("AutoBackup-HourToBackup", hourToSaveAt);
190 |
191 | if (!getConfig().contains("exceptions")) {
192 | exceptions.add("logs");
193 | exceptions.add("crash-reports");
194 | exceptions.add("backups");
195 | exceptions.add("dynmap");
196 | exceptions.add(".lock");
197 | exceptions.add("pixelprinter");
198 | }
199 | exceptions = (List) a("exceptions", exceptions);
200 |
201 | maxSaveSize = toByteSize((String) a("MaxSaveSize", "10G"));
202 | maxSaveFiles = (int) a("MaxFileSaved", 1000);
203 |
204 | deleteZipOnFTP = (boolean) a("DeleteZipOnFTPTransfer", false);
205 | deleteZipOnFail = (boolean) a("DeleteZipIfFailed", false);
206 | separator = (String) a("FolderSeparator", separator);
207 | if (saveTheConfig)
208 | saveConfig();
209 | if (automate) {
210 | final JavaPlugin thi = this;
211 | br = new BukkitRunnable() {
212 | @Override
213 | public void run() {
214 | Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance
215 | calendar.setTime(new Date()); // assigns calendar to given date
216 | int hour = calendar.get(Calendar.HOUR_OF_DAY);
217 |
218 | if (System.currentTimeMillis() - lastSave >= timedist && (hourToSaveAt==-1 || hourToSaveAt == hour)) {
219 | new BukkitRunnable() {
220 | @Override
221 | public void run() {
222 | getConfig().set("LastAutosave", lastSave = (System.currentTimeMillis()-5000));
223 | save(Bukkit.getConsoleSender());
224 | saveConfig();
225 | }
226 | }.runTaskLater(thi, 0);
227 | return;
228 | }
229 | }
230 | }.runTaskTimerAsynchronously(this, 20, 20*60);
231 | }
232 |
233 | new Metrics(this);
234 |
235 | /*if (Bukkit.getPluginManager().getPlugin("PluginConstructorAPI") == null)
236 | GithubDependDownloader.autoUpdate(this,
237 | new File(getDataFolder().getParentFile(), "PluginConstructorAPI.jar"), "ZombieStriker",
238 | "PluginConstructorAPI", "PluginConstructorAPI.jar");*/
239 |
240 | //new Updater(this, 280536);
241 |
242 | }
243 |
244 | @Override
245 | public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
246 |
247 | if (args.length == 1) {
248 | List list = new ArrayList<>();
249 | String[] commands = new String[]{"disableAutoSaver", "enableAutoSaver", "restore", "save","stop", "toggleOptions"};
250 | for (String f : commands) {
251 | if (f.toLowerCase().startsWith(args[0].toLowerCase()))
252 | list.add(f);
253 | }
254 | return list;
255 |
256 | }
257 |
258 | if (args.length > 1) {
259 | if (args[0].equalsIgnoreCase("restore")) {
260 | List list = new ArrayList<>();
261 | for (File f : getBackupFolder().listFiles()) {
262 | if (f.getName().toLowerCase().startsWith(args[1].toLowerCase()))
263 | list.add(f.getName());
264 | }
265 | return list;
266 | }
267 | }
268 | return super.onTabComplete(sender, command, alias, args);
269 | }
270 |
271 | @Override
272 | public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
273 | if (!sender.hasPermission("serverrestorer.command")) {
274 | sender.sendMessage(prefix + ChatColor.RED + " You do not have permission to use this command.");
275 | return true;
276 | }
277 | if (args.length == 0) {
278 | sender.sendMessage(ChatColor.GOLD + "---===+Server Restorer+===---");
279 | sender.sendMessage("/sr save : Saves the server");
280 | sender.sendMessage("/sr stop : Stops creating a backup of the server");
281 | sender.sendMessage("/sr restore : Restores server to previous backup (automatically restarts)");
282 | sender.sendMessage("/sr enableAutoSaver [1H,6H,1D,7D] : Configure how long it takes to autosave");
283 | sender.sendMessage("/sr disableAutoSaver : Disables the autosaver");
284 | sender.sendMessage("/sr toggleOptions : TBD");
285 | return true;
286 | }
287 | if (args[0].equalsIgnoreCase("restore")) {
288 | if(true) {
289 | sender.sendMessage(prefix+ "Restore feature is temporarily disabled. Please load the files manually.");
290 | return true;
291 | }
292 | if (!sender.hasPermission("serverrestorer.restore")) {
293 | sender.sendMessage(prefix + ChatColor.RED + " You do not have permission to use this command.");
294 | return true;
295 | }
296 | if (currentlySaving) {
297 | sender.sendMessage(prefix + " The server is currently being saved. Please wait.");
298 | return true;
299 | }
300 | if (args.length < 2) {
301 | sender.sendMessage(prefix + " A valid backup file is required.");
302 | return true;
303 | }
304 | File backup = new File(getBackupFolder(), args[1]);
305 | if (!backup.exists()) {
306 | sender.sendMessage(prefix + " The file \"" + args[1] + "\" does not exist.");
307 | return true;
308 | }
309 | restore(backup);
310 | sender.sendMessage(prefix + " Restoration complete.");
311 | return true;
312 | }
313 |
314 | if (args[0].equalsIgnoreCase("stop")) {
315 | if (!sender.hasPermission("serverrestorer.save")) {
316 | sender.sendMessage(prefix + ChatColor.RED + " You do not have permission to use this command.");
317 | return true;
318 | }
319 | if (currentlySaving) {
320 | currentlySaving=false;
321 | return true;
322 | }
323 | sender.sendMessage(prefix + " The server is not currently being saved.");
324 | return true;
325 | }
326 | if (args[0].equalsIgnoreCase("save")) {
327 | if (!sender.hasPermission("serverrestorer.save")) {
328 | sender.sendMessage(prefix + ChatColor.RED + " You do not have permission to use this command.");
329 | return true;
330 | }
331 | if (currentlySaving) {
332 | sender.sendMessage(prefix + " The server is currently being saved. Please wait.");
333 | return true;
334 | }
335 | save(sender);
336 | return true;
337 | }
338 | if (args[0].equalsIgnoreCase("disableAutoSaver")) {
339 | if (!sender.hasPermission("serverrestorer.save")) {
340 | sender.sendMessage(prefix + ChatColor.RED + " You do not have permission to use this command.");
341 | return true;
342 | }
343 | if (br != null)
344 | br.cancel();
345 | br = null;
346 | getConfig().set("enableautoSaving", false);
347 | saveConfig();
348 | sender.sendMessage(prefix + " Canceled delay.");
349 | }
350 | if (args[0].equalsIgnoreCase("enableAutoSaver")) {
351 | if (!sender.hasPermission("serverrestorer.save")) {
352 | sender.sendMessage(prefix + ChatColor.RED + " You do not have permission to use this command.");
353 | return true;
354 | }
355 | if (args.length == 1) {
356 | sender.sendMessage(prefix + " Please select a delay [E.G. 0.5H, 6H, 1D, 7D...]");
357 | return true;
358 | }
359 | String delay = args[1];
360 | getConfig().set("AutosaveDelay", delay);
361 | getConfig().set("enableautoSaving", true);
362 | saveConfig();
363 | if (br != null)
364 | br.cancel();
365 | br = null;
366 | br = new BukkitRunnable() {
367 | @Override
368 | public void run() {
369 | if (System.currentTimeMillis() - lastSave > timedist) {
370 | save(Bukkit.getConsoleSender());
371 | getConfig().set("LastAutosave", lastSave = System.currentTimeMillis());
372 | saveConfig();
373 | return;
374 | }
375 | }
376 | }.runTaskTimerAsynchronously(this, 20, 20 * 60 * 30);
377 |
378 | sender.sendMessage(prefix + " Set the delay to \"" + delay + "\".");
379 | }
380 | if (args[0].equalsIgnoreCase("toggleOptions")) {
381 | if (!sender.hasPermission("serverrestorer.save")) {
382 | sender.sendMessage(prefix + ChatColor.RED + " You do not have permission to use this command.");
383 | return true;
384 | }
385 | sender.sendMessage(prefix + " Coming soon !");
386 | return true;
387 | }
388 | return true;
389 | }
390 |
391 | public void save(CommandSender sender) {
392 | currentlySaving = true;
393 | sender.sendMessage(prefix + " Starting to save directory. Please wait.");
394 | List autosave = new ArrayList<>();
395 | for (World loaded : Bukkit.getWorlds()) {
396 | try {
397 | loaded.save();
398 | if (loaded.isAutoSave()) {
399 | autosave.add(loaded);
400 | loaded.setAutoSave(false);
401 | }
402 |
403 | } catch (Exception e) {
404 | }
405 | }
406 | new BukkitRunnable() {
407 | @Override
408 | public void run() {
409 | try {
410 | try {
411 | if(backups.listFiles().length > maxSaveFiles){
412 | for(int i = 0; i < backups.listFiles().length-maxSaveFiles; i++){
413 | File oldestBack = firstFileModified(backups);
414 | sender.sendMessage(prefix + ChatColor.RED + oldestBack.getName()
415 | + ": File goes over max amount of files that can be saved.");
416 | oldestBack.delete();
417 | }
418 | }
419 | for (int j = 0; j < Math.min(maxSaveFiles, backups.listFiles().length - 1); j++) {
420 | if (folderSize(backups) >= maxSaveSize) {
421 | File oldestBack = firstFileModified(backups);
422 | sender.sendMessage(prefix + ChatColor.RED + oldestBack.getName()
423 | + ": The current save goes over the max savesize, and so the oldest file has been deleted. If you wish to save older backups, copy them to another location.");
424 | oldestBack.delete();
425 | } else {
426 | break;
427 | }
428 | }
429 | } catch (Error | Exception e) {
430 | }
431 | final long time = lastSave = System.currentTimeMillis();
432 | Date d = new Date(lastSave);
433 | File zipFile = new File(getBackupFolder(),
434 | naming_format.replaceAll("%date%", dateformat.format(d)) + ".zip");
435 | if (!zipFile.exists()) {
436 | zipFile.getParentFile().mkdirs();
437 | zipFile = new File(getBackupFolder(),
438 | naming_format.replaceAll("%date%", dateformat.format(d)) + ".zip");
439 | zipFile.createNewFile();
440 | }
441 | zipFolder(getMasterFolder().getPath(), zipFile.getPath());
442 |
443 | long timeDif = (System.currentTimeMillis() - time) / 1000;
444 | String timeDifS = (((int) (timeDif / 60)) + "M, " + (timeDif % 60) + "S");
445 |
446 | if(!currentlySaving){
447 | for (World world : autosave)
448 | world.setAutoSave(true);
449 | sender.sendMessage(prefix + " Backup canceled.");
450 | cancel();
451 | return;
452 | }
453 |
454 | sender.sendMessage(prefix + " Done! Backup took:" + timeDifS);
455 | File tempBackupCheck = new File(getMasterFolder(), "backups");
456 | sender.sendMessage(prefix + " Compressed server with size of "
457 | + (humanReadableByteCount(folderSize(getMasterFolder())
458 | - (tempBackupCheck.exists() ? folderSize(tempBackupCheck) : 0), false))
459 | + " to " + humanReadableByteCount(zipFile.length(), false));
460 | currentlySaving = false;
461 | for (World world : autosave)
462 | world.setAutoSave(true);
463 | if (useSFTP) {
464 | try {
465 | sender.sendMessage(prefix + " Starting SFTP Transfer");
466 | JSch jsch = new JSch();
467 | Session session = jsch.getSession(userFTP, serverFTP, portFTP);
468 | session.setConfig("PreferredAuthentications", "password");
469 | session.setPassword(passwordFTP);
470 | session.connect(1000 * 20);
471 | Channel channel = session.openChannel("sftp");
472 | ChannelSftp sftp = (ChannelSftp) channel;
473 | sftp.connect(1000 * 20);
474 | } catch (Exception | Error e) {
475 | sender.sendMessage(
476 | prefix + " FAILED TO SFTP TRANSFER FILE: " + zipFile.getName() + ". ERROR IN CONSOLE.");
477 | if (deleteZipOnFail)
478 | zipFile.delete();
479 | e.printStackTrace();
480 | }
481 | } else if (useFTPS) {
482 | sender.sendMessage(prefix + " Starting FTPS Transfer");
483 | FileInputStream zipFileStream = new FileInputStream(zipFile);
484 | FTPSClient ftpClient = new FTPSClient();
485 | try {
486 | if (ftpClient.isConnected()) {
487 | sender.sendMessage(prefix + "FTPSClient was already connected. Disconnecting");
488 | ftpClient.logout();
489 | ftpClient.disconnect();
490 | ftpClient = new FTPSClient();
491 | }
492 | sendFTP(sender, zipFile, ftpClient, zipFileStream, removeFilePath);
493 | if (deleteZipOnFTP)
494 | zipFile.delete();
495 | } catch (Exception | Error e) {
496 | sender.sendMessage(
497 | prefix + " FAILED TO FTPS TRANSFER FILE: " + zipFile.getName() + ". ERROR IN CONSOLE.");
498 | if (deleteZipOnFail)
499 | zipFile.delete();
500 | e.printStackTrace();
501 | } finally {
502 | try {
503 | if (ftpClient.isConnected()) {
504 | sender.sendMessage(prefix + "Disconnecting");
505 | ftpClient.logout();
506 | ftpClient.disconnect();
507 | }
508 | } catch (IOException ex) {
509 | ex.printStackTrace();
510 | }
511 | }
512 | } else if (useFTP) {
513 | sender.sendMessage(prefix + " Starting FTP Transfer");
514 | FileInputStream zipFileStream = new FileInputStream(zipFile);
515 | FTPClient ftpClient = new FTPClient();
516 | try {
517 | if (ftpClient.isConnected()) {
518 | sender.sendMessage(prefix + "FTPClient was already connected. Disconnecting");
519 | ftpClient.logout();
520 | ftpClient.disconnect();
521 | ftpClient = new FTPClient();
522 | }
523 | sendFTP(sender, zipFile, ftpClient, zipFileStream, removeFilePath);
524 | if (deleteZipOnFTP)
525 | zipFile.delete();
526 | } catch (Exception | Error e) {
527 | sender.sendMessage(
528 | prefix + " FAILED TO FTP TRANSFER FILE: " + zipFile.getName() + ". ERROR IN CONSOLE.");
529 | if (deleteZipOnFail)
530 | zipFile.delete();
531 | e.printStackTrace();
532 | } finally {
533 | try {
534 | if (ftpClient.isConnected()) {
535 | sender.sendMessage(prefix + "Disconnecting");
536 | ftpClient.logout();
537 | ftpClient.disconnect();
538 | }
539 | } catch (IOException ex) {
540 | ex.printStackTrace();
541 | }
542 | }
543 | }
544 | } catch (Exception e) {
545 | e.printStackTrace();
546 | }
547 | }
548 | }.runTaskAsynchronously(this);
549 | }
550 |
551 | public void sendFTP(CommandSender sender, File zipFile, FTPClient ftpClient, FileInputStream zipFileStream, String path)
552 | throws SocketException, IOException {
553 | ftpClient.connect(serverFTP, portFTP);
554 | ftpClient.login(userFTP, passwordFTP);
555 | ftpClient.enterLocalPassiveMode();
556 |
557 | ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
558 |
559 | boolean done = ftpClient.storeFile(path + zipFile.getName(), zipFileStream);
560 | zipFileStream.close();
561 | if (done) {
562 | sender.sendMessage(prefix + " Transfered backup using FTP!");
563 | } else {
564 | sender.sendMessage(prefix + " Something failed (maybe)! Status=" + ftpClient.getStatus());
565 | }
566 |
567 | }
568 |
569 | public long toTime(String time) {
570 | long militime = 0;
571 | for(String split : time.split(",")) {
572 | split = split.trim();
573 | long k = 1;
574 | if (split.toUpperCase().endsWith("H")) {
575 | k *= 60 * 60;
576 | } else if (split.toUpperCase().endsWith("D")) {
577 | k *= 60 * 60 * 24;
578 | } else {
579 | k *= 60 * 60 * 24;
580 | }
581 | double j = Double.parseDouble(split.substring(0, split.length() - 1));
582 | militime += (j*k);
583 | }
584 | militime *= 1000;
585 | return militime;
586 | }
587 |
588 | public void restore(File backup) {
589 |
590 | //Kick all players
591 | for (Player player : Bukkit.getOnlinePlayers())
592 | player.kickPlayer(kickmessage);
593 |
594 | //Disable all plugins safely.
595 | for (Plugin p : Bukkit.getPluginManager().getPlugins()) {
596 | if (p != this) {
597 | try {
598 | Bukkit.getPluginManager().disablePlugin(p);
599 | } catch (Exception e) {
600 | e.printStackTrace();
601 | }
602 | }
603 | }
604 | //Unload all worlds.
605 | List names = new ArrayList<>();
606 | for (World w : Bukkit.getWorlds()) {
607 | for (Chunk c : w.getLoadedChunks()) {
608 | c.unload(false);
609 | }
610 | names.add(w.getName());
611 | Bukkit.unloadWorld(w, true);
612 | }
613 | for(String worldnames : names){
614 | File worldFile = new File(getMasterFolder(),worldnames);
615 | if(worldFile.exists())
616 | worldFile.delete();
617 | }
618 |
619 | //Start overriding files.
620 | File parentTo = getMasterFolder().getParentFile();
621 | try {
622 | byte[] buffer = new byte[1024];
623 | ZipInputStream zis = new ZipInputStream(new FileInputStream(backup));
624 | ZipEntry zipEntry = zis.getNextEntry();
625 | while (zipEntry != null) {
626 | try {
627 | File newFile = newFile(parentTo, zipEntry);
628 | FileOutputStream fos = new FileOutputStream(newFile);
629 | int len;
630 | while ((len = zis.read(buffer)) > 0) {
631 | fos.write(buffer, 0, len);
632 | }
633 | fos.close();
634 | zipEntry = zis.getNextEntry();
635 | } catch (Exception e) {
636 | e.printStackTrace();
637 | }
638 | }
639 | zis.closeEntry();
640 | zis.close();
641 | } catch (Exception e4) {
642 | e4.printStackTrace();
643 | }
644 | Bukkit.shutdown();
645 | }
646 |
647 | public void zipFolder(String srcFolder, String destZipFile) throws Exception {
648 | ZipOutputStream zip = null;
649 | FileOutputStream fileWriter = null;
650 |
651 | fileWriter = new FileOutputStream(destZipFile);
652 | zip = new ZipOutputStream(fileWriter);
653 |
654 |
655 | zip.setLevel(compression);
656 |
657 | addFolderToZip("", srcFolder, zip);
658 | zip.flush();
659 | zip.close();
660 | }
661 |
662 | private void addFileToZip(String path, String srcFile, ZipOutputStream zip) {
663 | try {
664 | File folder = new File(srcFile);
665 | if (!isExempt(srcFile)) {
666 |
667 | if(!currentlySaving)
668 | return;
669 | // this.savedBytes += folder.length();
670 | if (folder.isDirectory()) {
671 | addFolderToZip(path, srcFile, zip);
672 | } else {
673 | if (folder.getName().endsWith("jar")) {
674 | if (path.contains("plugins") && (!savePluiginJars) || (!path.contains("plugins") && (!saveServerJar))) {
675 | return;
676 | }
677 | }
678 |
679 | byte[] buf = new byte['?'];
680 |
681 | FileInputStream in = new FileInputStream(srcFile);
682 | zip.putNextEntry(new ZipEntry(path + separator + folder.getName()));
683 | int len;
684 | while ((len = in.read(buf)) > 0) {
685 | zip.write(buf, 0, len);
686 | }
687 | in.close();
688 | }
689 | }
690 | }catch (FileNotFoundException e4){
691 | Bukkit.getConsoleSender().sendMessage(prefix + " FAILED TO ZIP FILE: " + srcFile+" Reason: "+e4.getClass().getName());
692 | e4.printStackTrace();
693 | }catch (IOException e5){
694 | if(!srcFile.endsWith(".db")) {
695 | Bukkit.getConsoleSender().sendMessage(prefix + " FAILED TO ZIP FILE: " + srcFile + " Reason: " + e5.getClass().getName());
696 | e5.printStackTrace();
697 | }else{
698 | Bukkit.getConsoleSender().sendMessage(prefix + " Skipping file " + srcFile +" due to another process that has locked a portion of the file");
699 | }
700 |
701 | }
702 | }
703 |
704 | private void addFolderToZip(String path, String srcFolder, ZipOutputStream zip) {
705 | if ((!path.toLowerCase().contains("backups")) && (!isExempt(path))) {
706 | try {
707 | File folder = new File(srcFolder);
708 | String[] arrayOfString;
709 | int j = (arrayOfString = folder.list()).length;
710 | for (int i = 0; i < j; i++) {
711 | if(!currentlySaving)
712 | break;
713 | String fileName = arrayOfString[i];
714 | if (path.equals("")) {
715 | addFileToZip(folder.getName(), srcFolder + separator + fileName, zip);
716 | } else {
717 | addFileToZip(path + separator + folder.getName(), srcFolder + separator + fileName, zip);
718 | }
719 | }
720 | } catch (Exception e) {
721 | }
722 | }
723 | }
724 |
725 | private long toByteSize(String s) {
726 | long k = Long.parseLong(s.substring(0, s.length() - 1));
727 | if (s.toUpperCase().endsWith("G")) {
728 | k *= 1000 * 1000 * 1000;
729 | } else if (s.toUpperCase().endsWith("M")) {
730 | k *= 1000 * 1000;
731 | } else if (s.toUpperCase().endsWith("K")) {
732 | k *= 1000;
733 | } else {
734 | k *= 10;
735 | }
736 | return k;
737 | }
738 | }
739 |
--------------------------------------------------------------------------------