Skip to content

Commit

Permalink
Fix Apache HttpClient Mime embedding
Browse files Browse the repository at this point in the history
  • Loading branch information
MaidThatPrograms committed Aug 25, 2020
1 parent 05c6ab3 commit fc4228a
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 60 deletions.
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
.gradle
.settings
.*
gradle
run
.classpath
.project
gradlew
gradlew.bat
*.launch
41 changes: 15 additions & 26 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ buildscript {

apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'eclipse'
version = '1.15.2-0.0.1.0'
version = '1.15.2-0.0.1.1'
group = 'cmsc389e.circuitry'
archivesBaseName = 'circuitry'
compileJava.options.compilerArgs << '-proc:none'
Expand All @@ -26,43 +26,32 @@ minecraft {
runs {
client {
workingDirectory project.file('run')

mods {
circuitry {
source sourceSets.main
}
circuitry.source sourceSets.main
}
}

server {
workingDirectory project.file('run')

mods {
circuitry {
source sourceSets.main
}
circuitry.source sourceSets.main
}
}
}
}

dependencies {
minecraft 'net.minecraftforge:forge:1.15.2-31.2.0'
compile 'org.apache.httpcomponents:httpmime:+'
}

jar {
manifest {
attributes([
'Implementation-Version': '${version}'
])
}

from {
configurations.compile.filter {
it.getName().startsWith('httpmime')
}.collect {
zipTree(it)
}
}
}
jar.manifest.attributes (
'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
'Implementation-Title': project.name,
'Implementation-Vendor': project.archivesBaseName,
'Implementation-Version': '${version}',
'Specification-Title': project.name,
'Specification-Vendor': project.archivesBaseName,
'Specification-Version': '${version}'
)
2 changes: 1 addition & 1 deletion src/main/java/cmsc389e/circuitry/Circuitry.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public int size() {
frozen = false;
return size;
}
}, "drawnChatLines");
}, "field_146253_i"); // drawnChatLines
}

public Circuitry() {
Expand Down
14 changes: 6 additions & 8 deletions src/main/java/cmsc389e/circuitry/client/EventHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,12 @@ public static void onGuiOpen(GuiOpenEvent event) {
os -> os.openFile(FMLPaths.MODSDIR.get().toFile()));

IModInfo info = list.getModContainerById(Circuitry.MODID).get().getModInfo();
if (!info.getVersion().getQualifier().equals("NONE")) {
CheckResult result = VersionChecker.getResult(info);
if (result.status == Status.OUTDATED)
alert(event, info.getDisplayName() + " is out of date.",
"You must update to version " + result.target
+ " before proceeding.\nOpen Link will bring you to the page below:",
result.url, "Open Link", os -> os.openURI(result.url));
}
CheckResult result = VersionChecker.getResult(info);
if (result.status == Status.OUTDATED)
alert(event, info.getDisplayName() + " is out of date.",
"You must update to version " + result.target
+ " before proceeding.\nOpen Link will bring you to the page below:",
result.url, "Open Link", os -> os.openURI(result.url));
}
}

Expand Down
138 changes: 138 additions & 0 deletions src/main/java/cmsc389e/circuitry/common/MultipartFormEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package cmsc389e.circuitry.common;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;

import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.ByteArrayBuffer;

import com.google.common.collect.ImmutableMap;

/**
* Modified version of Apache HttpClient Mime's MultipartFormEntity class to be
* extremely minimal.<br>
* <br>
* <a
* href=https://hc.apache.org/httpcomponents-client-4.3.x/httpmime/project-reports.html>Apache
* HttpClient Mime</a>
*/
public class MultipartFormEntity implements HttpEntity {
private static final ByteArrayBuffer CR_LF = encode("\r\n"), FIELD_SEP = encode(": "), TWO_DASHES = encode("--");

private static ByteArrayBuffer encode(String string) {
ByteBuffer encoded = Consts.ASCII.encode(CharBuffer.wrap(string));
ByteArrayBuffer buffer = new ByteArrayBuffer(encoded.remaining());
buffer.append(encoded.array(), encoded.position(), encoded.remaining());
return buffer;
}

private static void writeBytes(ByteArrayBuffer buffer, OutputStream out) throws IOException {
out.write(buffer.buffer(), 0, buffer.length());
}

private final String boundary;
private final Header contentType;
private final byte[] data;
private final Map<String, String> header;
private final long contentLength;

public MultipartFormEntity(String name, String fileName, byte[] data) throws IOException {
Random random = new Random();
int count = random.nextInt(11) + 30;
StringBuilder boundary = new StringBuilder();
char[] multipartChars = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
for (int i = 0; i < count; i++)
boundary.append(multipartChars[random.nextInt(multipartChars.length)]);

this.boundary = boundary.toString();
contentType = new BasicHeader(HTTP.CONTENT_TYPE, "multipart/form-data; boundary=" + boundary);
this.data = data;
header = ImmutableMap.of("content-disposition",
"form-data; name=\"" + name + "\"; filename=\"" + fileName + "\"", "content-type",
ContentType.DEFAULT_BINARY.getMimeType(), "content-transfer-encoding", "binary");

ByteArrayOutputStream out = new ByteArrayOutputStream();
writeTo(out, false);
contentLength = data.length + out.toByteArray().length;
}

@Deprecated
@Override
public void consumeContent() throws UnsupportedOperationException {
if (isStreaming())
throw new UnsupportedOperationException("Streaming entity does not implement #consumeContent()");
}

@Override
public InputStream getContent() {
throw new UnsupportedOperationException("Multipart form entity does not implement #getContent()");
}

@Override
public Header getContentEncoding() {
return null;
}

@Override
public long getContentLength() {
return contentLength;
}

@Override
public Header getContentType() {
return contentType;
}

@Override
public boolean isChunked() {
return !isRepeatable();
}

@Override
public boolean isRepeatable() {
return contentLength != -1;
}

@Override
public boolean isStreaming() {
return !isRepeatable();
}

@Override
public void writeTo(OutputStream out) throws IOException {
writeTo(out, true);
}

private void writeTo(OutputStream out, boolean write) throws IOException {
ByteArrayBuffer boundary = encode(this.boundary);
writeBytes(TWO_DASHES, out);
writeBytes(boundary, out);
writeBytes(CR_LF, out);
for (Entry<String, String> entry : header.entrySet()) {
writeBytes(encode(entry.getKey()), out);
writeBytes(FIELD_SEP, out);
writeBytes(encode(entry.getValue()), out);
writeBytes(CR_LF, out);
}
writeBytes(CR_LF, out);
if (write)
out.write(data);
writeBytes(CR_LF, out);
writeBytes(TWO_DASHES, out);
writeBytes(boundary, out);
writeBytes(TWO_DASHES, out);
writeBytes(CR_LF, out);
}
}
21 changes: 10 additions & 11 deletions src/main/java/cmsc389e/circuitry/common/block/NodeBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,20 @@ public boolean hasTileEntity(BlockState state) {
}

/**
* Called when a {@link InNodeBlock} is right-clicked and the
* {@link PlayerEntity} is not crouching. The {@link World} is not checked
* whether it is remote since all this method does is modify
* {@link NodeTileEntity#index} at the {@link BlockPos}. On {@link Chunk} load,
* the client-side {@link NodeTileEntity} is synced to the server-side one. That
* means {@link NodeTileEntity#index} will always be synchronized.
* Called when a {@link NodeBlock} is right-clicked and the {@link PlayerEntity}
* is not crouching. The {@link World} is not checked whether it is remote since
* all this method does is modify {@link NodeTileEntity#index} at the
* {@link BlockPos}. On {@link Chunk} load, the client-side
* {@link NodeTileEntity} is synced to the server-side one. That means
* {@link NodeTileEntity#index} will always be synchronized.
*
* @param state the {@link BlockState} of the {@link InNodeBlock} that was
* clicked
* @param worldIn the {@link World} that the {@link InNodeBlock} was clicked in
* @param pos the {@link BlockPos} of the {@link InNodeBlock} that was
* @param state the {@link BlockState} of the {@link NodeBlock} that was
* clicked
* @param worldIn the {@link World} that the {@link NodeBlock} was clicked in
* @param pos the {@link BlockPos} of the {@link NodeBlock} that was clicked
* @param player the {@link PlayerEntity} who did the clicking
* @param handIn the {@link Hand} with which the {@link PlayerEntity} clicked
* @param hit where on the {@link InNodeBlock}'s bounds it was hit
* @param hit where on the {@link NodeBlock}'s bounds it was hit
* @return {@link ActionResultType#SUCCESS}, which tells the game that the
* action was consumed correctly
* @deprecated
Expand Down
11 changes: 3 additions & 8 deletions src/main/java/cmsc389e/circuitry/common/command/TestCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
Expand All @@ -23,6 +21,7 @@
import com.mojang.brigadier.context.CommandContext;

import cmsc389e.circuitry.common.Config;
import cmsc389e.circuitry.common.MultipartFormEntity;
import cmsc389e.circuitry.common.Tester;
import net.minecraft.command.CommandException;
import net.minecraft.command.CommandSource;
Expand Down Expand Up @@ -127,12 +126,8 @@ private static int submit(CommandContext<CommandSource> context, String campusUI
zip.close();

execute(source, client, base + "SubmitProjectViaEclipse",
MultipartEntityBuilder.create()
.addBinaryBody("submittedFiles", out.toByteArray(), ContentType.DEFAULT_BINARY,
"submit.zip")
.build(),
"courseName", "CMSC389E", "cvsAccount", Config.cvsAccount.get(), "oneTimePassword",
Config.oneTimePassword.get());
new MultipartFormEntity("submittedfiles", "submit.zip", out.toByteArray()), "courseName",
"CMSC389E", "cvsAccount", Config.cvsAccount.get(), "oneTimePassword", Config.oneTimePassword.get());
} catch (IOException e) {
e.printStackTrace();
throw new CommandException(new StringTextComponent(e.getLocalizedMessage()));
Expand Down
5 changes: 3 additions & 2 deletions update.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"homepage": "https://github.com/CMSC-389E/mod-framework-and-testing-framework/releases",
"1.15.2": {
"1.15.2-0.0.1.1": "Fix Apache HttpClient Mime embedding",
"1.15.2-0.0.1.0": "Update to 1.15.2."
},
"1.12.2": {
Expand All @@ -13,8 +14,8 @@
"1.12.2-0.0.1.0-beta3": "-Implement commands.\n-Fix minor bugs."
},
"promos": {
"1.15.2-latest": "1.15.2-0.0.1.0",
"1.15.2-recommended": "1.15.2-0.0.1.0",
"1.15.2-latest": "1.15.2-0.0.1.1",
"1.15.2-recommended": "1.15.2-0.0.1.1",

"1.12.2-latest": "1.12.2-1.0.1.0",
"1.12.2-recommended": "1.12.2-1.0.1.0"
Expand Down

0 comments on commit fc4228a

Please sign in to comment.