public void testGetAssetsZipFileBadAssets() throws Exception { String userId = "1"; long projectId = 2; byte[] data = {0}; List<String> sourceFiles = new ArrayList<String>(); sourceFiles.add("assets/badkitty.png"); sourceFiles.add("assets/meow.mp3"); sourceFiles.add("src/appinventor/ai_user/HelloPurr/Screen1.blk"); sourceFiles.add("src/appinventor/ai_user/HelloPurr/Screen1.scm"); sourceFiles.add("youngandroidproject/project.properties"); EasyMock.expect(storageIo.getProjectSourceFiles(userId, projectId)).andReturn(sourceFiles); EasyMock.expect( storageIo.downloadRawFile( EasyMock.eq(userId), EasyMock.eq(projectId), EasyMock.eq("assets/badkitty.png"))) .andThrow(new RuntimeException()); EasyMock.expect( storageIo.downloadRawFile( EasyMock.eq(userId), EasyMock.eq(projectId), EasyMock.eq("assets/meow.mp3"))) .andReturn(data); control.replay(); List<String> zipEntries = getZipEntries(yaWebStart.getAssetsZipFile(userId, projectId)); ListAssert.assertContains(zipEntries, "assets/meow.mp3"); ListAssert.assertContains(zipEntries, "badassets/badkitty.png"); }
@Override public void importUserFile(String userId, String fileName, InputStream uploadedFileStream) throws IOException { byte[] content = ByteStreams.toByteArray(uploadedFileStream); // If the file already exists, we will overwrite the content. List<String> userFiles = storageIo.getUserFiles(userId); if (!userFiles.contains(fileName)) { storageIo.addFilesToUser(userId, fileName); } storageIo.uploadRawUserFile(userId, fileName, content); }
@Override public Set<String> getProjectNames(final String userId) { List<Long> projectIds = storageIo.getProjects(userId); Iterable<String> names = Iterables.transform( projectIds, new Function<Long, String>() { @Override public String apply(Long projectId) { return storageIo.getProjectName(userId, projectId); } }); return ImmutableSet.copyOf(names); }
@VisibleForTesting public long importFile( String userId, long projectId, String fileName, InputStream uploadedFileStream) throws FileImporterException, IOException { int maxAssetSizeBytes = (int) (maxAssetSizeMegs.get() * 1024 * 1024); int maxSizeBytes = Math.min(maxAssetSizeBytes, storageIo.getMaxJobSizeBytes()); BufferedInputStream bis = new BufferedInputStream(uploadedFileStream); ByteArrayOutputStream os = new ByteArrayOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(os); // Alledgedly since it is buffered, reading in units of one byte // should be as fast as many bytes, but we can always adjust this. int bytes = 0; long fileLength = 0; byte[] buffer = new byte[1]; while ((bytes = bis.read(buffer, 0, buffer.length)) != -1) { bos.write(buffer, 0, bytes); fileLength += bytes; } bos.flush(); // First check the file length, to avoid loading the file into memory if it is too large anyhow. if (fileLength > maxSizeBytes) { throw new FileImporterException(UploadResponse.Status.FILE_TOO_LARGE); } byte[] content = os.toByteArray(); // If the file already exists, we will overwrite the content. List<String> sourceFiles = storageIo.getProjectSourceFiles(userId, projectId); if (!sourceFiles.contains(fileName)) { storageIo.addSourceFilesToProject(userId, projectId, false, fileName); } return storageIo.uploadRawFileForce(projectId, fileName, userId, content); }
/** * Gets the current Motd * * @return the current Motd */ @Override public Motd getMotd() { return storageIo.getCurrentMotd(); }
@Override public UserProject importProject( String userId, String projectName, InputStream uploadedFileStream, @Nullable String projectHistory) throws FileImporterException, IOException { // The projectName parameter has already been validated, including checking for an // existing project with the same name. (See TextValidators.checkNewProjectName). // Begin creating the project. Project project = new Project(projectName); project.setProjectType(YoungAndroidProjectNode.YOUNG_ANDROID_PROJECT_TYPE); // As we process the ZipEntry for each file, we'll adjust the directory structure so that it is // appropriate for this user. // Here we get the information (such as the qualified form name) that we'll need to do that. String qualifiedFormName = StringUtils.getQualifiedFormName(storageIo.getUser(userId).getUserEmail(), projectName); String srcDirectory = YoungAndroidProjectService.getSourceDirectory(qualifiedFormName); ZipInputStream zin = new ZipInputStream(uploadedFileStream); boolean isProjectArchive = false; // have we found at least one project properties file? try { // Extract files while (true) { ZipEntry entry; try { entry = zin.getNextEntry(); if (entry == null) { break; } } catch (ZipException e) { // The uploaded file is not a valid zip file throw new FileImporterException(UploadResponse.Status.NOT_PROJECT_ARCHIVE); } if (!entry.isDirectory()) { String fileName = entry.getName(); if (fileName.equals(YoungAndroidProjectService.PROJECT_PROPERTIES_FILE_NAME)) { // The content for the youngandroidproject/project.properties file must be regenerated // so that it contains the correct entries for "main" and "name", which are dependent on // the projectName and qualifiedFormName. String content = YoungAndroidProjectService.getProjectPropertiesFileContents( projectName, qualifiedFormName, null, null, null, null); project.addTextFile(new TextFile(fileName, content)); isProjectArchive = true; } else if (fileName.equals(FileExporter.REMIX_INFORMATION_FILE_PATH) || fileName.equals(StorageUtil.ANDROID_KEYSTORE_FILENAME)) { // If the remix information file is present, we ignore it. In the past, a remix // information file was saved in the zip when project source was downloaded and // retrieved from the zip when it was uploaded. However, we no longer do that because // we don't have a way to verify that the contents of the remix information file is // accurate during the upload. // If a keystore file is present we ignore that too for now, since // we don't have per-project keystores. The only way to get such a // source zip at the moment is using the admin functionality to // download another user's project source. continue; } else { if (fileName.startsWith(YoungAndroidProjectService.SRC_FOLDER)) { // For files within the src folder, we need to update the directory that we put files // in. Adjust the fileName so that it corresponds to this project's package. fileName = srcDirectory + '/' + StorageUtil.basename(fileName); } // Get the file content from the ZipEntry. ByteArrayOutputStream contentStream = new ByteArrayOutputStream(); ByteStreams.copy(zin, contentStream); project.addRawFile(new RawFile(fileName, contentStream.toByteArray())); } } } } finally { zin.close(); } if (!isProjectArchive) { // The uploaded file seems to be a valid zip file, but it doesn't contain the project // properties file. throw new FileImporterException(UploadResponse.Status.NOT_PROJECT_ARCHIVE); } // Set project history if provided if (projectHistory != null) { project.setProjectHistory(projectHistory); } String settings = YoungAndroidProjectService.getProjectSettings(null, null, null, null); long projectId = storageIo.createProject(userId, project, settings); return storageIo.getUserProject(userId, projectId); }