Skip to content

Commit 08d98ac

Browse files
authored
Merge pull request #17 from codedx/feature/nested-archives
Add support for .ear files and a less naive short-circuit file checker.
2 parents 745125e + b66fb5c commit 08d98ac

File tree

6 files changed

+64
-20
lines changed

6 files changed

+64
-20
lines changed

codepulse/src/main/scala/bootstrap/liftweb/AppCleanup.scala

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,23 @@
2020
package bootstrap.liftweb
2121

2222
object AppCleanup {
23-
private var hooks: List[() => Unit] = Nil
23+
private var preShutdownHooks: List[() => Unit] = Nil
2424

25-
def add(cleanup: () => Unit) = hooks ::= cleanup
25+
private var shutdownHooks: List[() => Unit] = Nil
26+
27+
def addPreShutdownHook(cleanup: () => Unit) = preShutdownHooks ::= cleanup
28+
29+
def addShutdownHook(cleanup: () => Unit) = shutdownHooks ::= cleanup
2630

2731
def runCleanup() = {
28-
hooks.reverseIterator.foreach { _() }
32+
try {
33+
println("Running PreShutdownHooks")
34+
preShutdownHooks.reverseIterator.foreach { _() }
35+
36+
println("Running ShutdownHooks")
37+
shutdownHooks.reverseIterator.foreach { _() }
38+
} catch {
39+
case e: Throwable => e.printStackTrace
40+
}
2941
}
3042
}

codepulse/src/main/scala/com/secdec/codepulse/tracer/ProjectFileUploadHandler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class ProjectFileUploadHandler(projectManager: ProjectManager) extends RestHelpe
5656
case UploadPath("create") Post req => fallbackResponse {
5757
for {
5858
(inputFile, originalName, cleanup) <- getReqFile(req) ?~! "Creating a new project requires a file"
59-
_ <- ProjectUploadData.checkForBinaryZip(inputFile) ?~ {
59+
_ <- ProjectUploadData.checkForClassesInNestedArchive(inputFile) ?~ {
6060
s"The file you picked doesn't have any compiled Java files."
6161
}
6262
name <- req.param("name") ?~ "You must specify a name"

codepulse/src/main/scala/com/secdec/codepulse/tracer/ProjectManager.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ import reactive.Observing
4444
object ProjectManager {
4545
lazy val defaultActorSystem = {
4646
val sys = ActorSystem("ProjectManagerSystem")
47-
AppCleanup.add { () => sys.shutdown() }
47+
AppCleanup.addShutdownHook { () =>
48+
sys.shutdown()
49+
sys.awaitTermination()
50+
println("Shutdown ProjectManager's ActorSystem")
51+
}
4852
sys
4953
}
5054
}
@@ -196,6 +200,9 @@ class ProjectManager(val actorSystem: ActorSystem) extends Observing {
196200
}
197201

198202
// Also make sure any dirty projects are saved when exiting
199-
AppCleanup.add { () => flushProjects }
203+
AppCleanup.addPreShutdownHook { () =>
204+
flushProjects
205+
println("Flushed ProjectManager projects")
206+
}
200207

201208
}

codepulse/src/main/scala/com/secdec/codepulse/tracer/ProjectUploadData.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ object ProjectUploadData {
6969
}
7070
}
7171

72+
def checkForClassesInNestedArchive(file: File): Boolean = {
73+
ZipEntryChecker.findFirstEntry(file) { (filename, entry, contents) =>
74+
!entry.isDirectory && FilenameUtils.getExtension(entry.getName) == "class"
75+
}
76+
}
77+
7278
/** A preliminary check on a File to see if it looks like an
7379
* exported .pulse file.
7480
*/

codepulse/src/main/scala/com/secdec/codepulse/tracer/TraceServer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ object TraceServer {
3636
private implicit lazy val socketServer = {
3737
val ss = SocketServer.default(com.secdec.codepulse.userSettings.tracePort)
3838
ss.start()
39-
AppCleanup.add { () =>
39+
AppCleanup.addPreShutdownHook { () =>
4040
ss.shutdown
4141
println("Shutdown TracerServer's socketServer")
4242
}

codepulse/src/main/scala/com/secdec/codepulse/util/ZipEntryChecker.scala

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,9 @@
1919

2020
package com.secdec.codepulse.util
2121

22-
import java.io.BufferedInputStream
23-
import java.io.File
24-
import java.io.FileInputStream
25-
import java.io.InputStream
26-
import java.util.zip.ZipEntry
27-
import java.util.zip.ZipFile
28-
import java.util.zip.ZipInputStream
29-
30-
import scala.collection.JavaConversions._
31-
import scala.util.Failure
32-
import scala.util.Success
33-
import scala.util.Try
22+
import java.io.{ BufferedInputStream, File, FileInputStream, InputStream }
23+
import java.util.zip.{ ZipEntry, ZipFile, ZipInputStream }
24+
import scala.util.{ Failure, Success, Try }
3425

3526
import org.apache.commons.io.FilenameUtils
3627
import org.apache.commons.io.input.CloseShieldInputStream
@@ -61,7 +52,7 @@ trait ZipEntryChecker {
6152
}
6253

6354
def isZip(name: String): Boolean = FilenameUtils.getExtension(name) match {
64-
case "zip" | "jar" | "war" => true
55+
case "zip" | "ear" | "jar" | "war" => true
6556
case _ => false
6657
}
6758

@@ -95,4 +86,32 @@ trait ZipEntryChecker {
9586
stream.close
9687
}
9788
}
89+
90+
def findFirstEntry(file: File, recursive: Boolean = true)(predicate: (String, ZipEntry, InputStream) => Boolean): Boolean = {
91+
val stream = new BufferedInputStream(new FileInputStream(file))
92+
93+
try findFirstEntry(file.getName, stream, recursive)(predicate) finally stream.close
94+
}
95+
96+
def findFirstEntry(filename: String, stream: InputStream, recursive: Boolean)(predicate: (String, ZipEntry, InputStream) => Boolean): Boolean = {
97+
val zipStream = new ZipInputStream(stream)
98+
99+
try {
100+
val entryStream = Stream.continually(Try { zipStream.getNextEntry })
101+
.map(_.toOption.flatMap { Option(_) })
102+
.takeWhile(_.isDefined)
103+
.flatten
104+
.filterNot(ZipCleaner.shouldFilter)
105+
106+
entryStream.exists { entry =>
107+
lazy val recurse = recursive &&
108+
isZip(entry.getName) &&
109+
findFirstEntry(s"$filename/${entry.getName}", new CloseShieldInputStream(zipStream), true)(predicate)
110+
111+
predicate(filename, entry, zipStream) || recurse
112+
}
113+
} finally {
114+
zipStream.close
115+
}
116+
}
98117
}

0 commit comments

Comments
 (0)