Merge pull request #3055 from ffissore/other-packages

Allow listing other boards in boards manager
This commit is contained in:
Federico Fissore 2015-05-04 16:55:41 +02:00
commit 87fb45c3b4
47 changed files with 1514 additions and 510 deletions

View File

@ -20,8 +20,8 @@
<classpathentry kind="lib" path="app/lib/jmdns-3.4.1.jar"/> <classpathentry kind="lib" path="app/lib/jmdns-3.4.1.jar"/>
<classpathentry kind="lib" path="app/lib/jsch-0.1.50.jar"/> <classpathentry kind="lib" path="app/lib/jsch-0.1.50.jar"/>
<classpathentry kind="lib" path="app/lib/jssc-2.8.0.jar"/> <classpathentry kind="lib" path="app/lib/jssc-2.8.0.jar"/>
<classpathentry kind="lib" path="app/lib/bcpg-jdk15on-149.jar"/> <classpathentry kind="lib" path="app/lib/bcpg-jdk15on-152.jar"/>
<classpathentry kind="lib" path="app/lib/bcprov-jdk15on-149.jar"/> <classpathentry kind="lib" path="app/lib/bcprov-jdk15on-152.jar"/>
<classpathentry kind="lib" path="app/lib/jackson-core-2.2.3.jar"/> <classpathentry kind="lib" path="app/lib/jackson-core-2.2.3.jar"/>
<classpathentry kind="lib" path="app/lib/jackson-databind-2.2.3.jar"/> <classpathentry kind="lib" path="app/lib/jackson-databind-2.2.3.jar"/>
<classpathentry kind="lib" path="app/lib/jackson-module-mrbean-2.2.3.jar"/> <classpathentry kind="lib" path="app/lib/jackson-module-mrbean-2.2.3.jar"/>

View File

@ -7,8 +7,8 @@
<classpathentry kind="lib" path="lib/jna.jar"/> <classpathentry kind="lib" path="lib/jna.jar"/>
<classpathentry kind="lib" path="lib/ecj.jar"/> <classpathentry kind="lib" path="lib/ecj.jar"/>
<classpathentry kind="lib" path="lib/apple.jar"/> <classpathentry kind="lib" path="lib/apple.jar"/>
<classpathentry kind="lib" path="lib/bcpg-jdk15on-149.jar"/> <classpathentry kind="lib" path="lib/bcpg-jdk15on-152.jar"/>
<classpathentry kind="lib" path="lib/bcprov-jdk15on-149.jar"/> <classpathentry kind="lib" path="lib/bcprov-jdk15on-152.jar"/>
<classpathentry kind="lib" path="lib/commons-codec-1.7.jar"/> <classpathentry kind="lib" path="lib/commons-codec-1.7.jar"/>
<classpathentry kind="lib" path="lib/commons-compress-1.8.jar"/> <classpathentry kind="lib" path="lib/commons-compress-1.8.jar"/>
<classpathentry kind="lib" path="lib/commons-exec-1.1.jar"/> <classpathentry kind="lib" path="lib/commons-exec-1.1.jar"/>

View File

@ -99,6 +99,8 @@
<fileset dir="test" includes="**/*.txt" /> <fileset dir="test" includes="**/*.txt" />
<fileset dir="test" includes="**/*.properties" /> <fileset dir="test" includes="**/*.properties" />
<fileset dir="test" includes="**/*.ino" /> <fileset dir="test" includes="**/*.ino" />
<fileset dir="test" includes="**/*.json*" />
<fileset dir="test" includes="**/*.key" />
</copy> </copy>
<junit printsummary="yes" dir="${work.dir}" fork="true"> <junit printsummary="yes" dir="${work.dir}" fork="true">

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -32,7 +32,7 @@ import cc.arduino.contributions.DownloadableContributionBuiltInAtTheBottomCompar
import cc.arduino.contributions.filters.InstalledPredicate; import cc.arduino.contributions.filters.InstalledPredicate;
import cc.arduino.contributions.packages.ContributedPackage; import cc.arduino.contributions.packages.ContributedPackage;
import cc.arduino.contributions.packages.ContributedPlatform; import cc.arduino.contributions.packages.ContributedPlatform;
import cc.arduino.contributions.packages.ContributionsIndex; import cc.arduino.contributions.packages.ContributionsIndexer;
import cc.arduino.contributions.ui.FilteredAbstractTableModel; import cc.arduino.contributions.ui.FilteredAbstractTableModel;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
@ -113,16 +113,16 @@ public class ContributionIndexTableModel extends FilteredAbstractTableModel<Cont
private Class<?>[] columnTypes = {ContributedPlatform.class}; private Class<?>[] columnTypes = {ContributedPlatform.class};
private ContributionsIndex index; private ContributionsIndexer indexer;
public void setIndex(ContributionsIndex _index) { public void setIndexer(ContributionsIndexer indexer) {
index = _index; this.indexer = indexer;
} }
public void updateIndexFilter(String filters[], Predicate<ContributedPlatform>... additionalFilters) { public void updateIndexFilter(String filters[], Predicate<ContributedPlatform>... additionalFilters) {
contributions.clear(); contributions.clear();
Predicate<ContributedPlatform> filter = Predicates.and(additionalFilters); Predicate<ContributedPlatform> filter = Predicates.and(additionalFilters);
for (ContributedPackage pack : index.getPackages()) { for (ContributedPackage pack : indexer.getPackages()) {
for (ContributedPlatform platform : pack.getPlatforms()) { for (ContributedPlatform platform : pack.getPlatforms()) {
if (!filter.apply(platform)) { if (!filter.apply(platform)) {
continue; continue;

View File

@ -28,15 +28,11 @@
*/ */
package cc.arduino.contributions.packages.ui; package cc.arduino.contributions.packages.ui;
import cc.arduino.contributions.ui.InstallerJDialogUncaughtExceptionHandler;
import cc.arduino.contributions.packages.ContributedPlatform; import cc.arduino.contributions.packages.ContributedPlatform;
import cc.arduino.contributions.packages.ContributionInstaller; import cc.arduino.contributions.packages.ContributionInstaller;
import cc.arduino.contributions.packages.ContributionsIndexer; import cc.arduino.contributions.packages.ContributionsIndexer;
import cc.arduino.contributions.packages.DownloadableContribution; import cc.arduino.contributions.packages.DownloadableContribution;
import cc.arduino.contributions.ui.DropdownItem; import cc.arduino.contributions.ui.*;
import cc.arduino.contributions.ui.FilteredAbstractTableModel;
import cc.arduino.contributions.ui.InstallerJDialog;
import cc.arduino.contributions.ui.InstallerTableCell;
import cc.arduino.utils.Progress; import cc.arduino.utils.Progress;
import processing.app.I18n; import processing.app.I18n;
@ -95,7 +91,7 @@ public class ContributionManagerUI extends InstallerJDialog {
categoryChooser.removeActionListener(categoryChooserActionListener); categoryChooser.removeActionListener(categoryChooserActionListener);
getContribModel().setIndex(indexer.getIndex()); getContribModel().setIndexer(indexer);
categoryFilter = null; categoryFilter = null;
categoryChooser.removeAllItems(); categoryChooser.removeAllItems();
@ -106,7 +102,7 @@ public class ContributionManagerUI extends InstallerJDialog {
// Enable categories combo only if there are two or more choices // Enable categories combo only if there are two or more choices
categoryChooser.addItem(new DropdownAllCoresItem()); categoryChooser.addItem(new DropdownAllCoresItem());
Collection<String> categories = indexer.getIndex().getCategories(); Collection<String> categories = indexer.getCategories();
for (String s : categories) { for (String s : categories) {
categoryChooser.addItem(new DropdownCoreOfCategoryItem(s)); categoryChooser.addItem(new DropdownCoreOfCategoryItem(s));
} }
@ -152,7 +148,8 @@ public class ContributionManagerUI extends InstallerJDialog {
public void run() { public void run() {
try { try {
setProgressVisible(true, ""); setProgressVisible(true, "");
installer.updateIndex(); List<String> downloadedPackageIndexFiles = installer.updateIndex();
installer.deleteUnknownFiles(downloadedPackageIndexFiles);
onIndexesUpdated(); onIndexesUpdated();
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);

View File

@ -22,6 +22,7 @@
package processing.app; package processing.app;
import cc.arduino.DefaultUncaughtExceptionHandler;
import cc.arduino.contributions.DownloadableContributionVersionComparator; import cc.arduino.contributions.DownloadableContributionVersionComparator;
import cc.arduino.contributions.VersionHelper; import cc.arduino.contributions.VersionHelper;
import cc.arduino.contributions.libraries.ContributedLibrary; import cc.arduino.contributions.libraries.ContributedLibrary;
@ -321,7 +322,8 @@ public class Base {
lastStatus = progress.getStatus(); lastStatus = progress.getStatus();
} }
}; };
installer.updateIndex(); List<String> downloadedPackageIndexFiles = installer.updateIndex();
installer.deleteUnknownFiles(downloadedPackageIndexFiles);
indexer.parseIndex(); indexer.parseIndex();
indexer.syncWithFilesystem(getHardwareFolder()); indexer.syncWithFilesystem(getHardwareFolder());
@ -342,7 +344,7 @@ public class Base {
System.exit(1); System.exit(1);
} }
ContributedPlatform installed = indexer.getIndex().getInstalled(boardToInstallParts[0], boardToInstallParts[1]); ContributedPlatform installed = indexer.getInstalled(boardToInstallParts[0], boardToInstallParts[1]);
if (!selected.isReadOnly()) { if (!selected.isReadOnly()) {
installer.install(selected); installer.install(selected);
@ -2404,14 +2406,6 @@ public class Base {
} }
/**
* Return an InputStream for a file inside the Processing lib folder.
*/
static public InputStream getLibStream(String filename) throws IOException {
return BaseNoGui.getLibStream(filename);
}
// ................................................................... // ...................................................................
@ -2429,17 +2423,22 @@ public class Base {
*/ */
static public byte[] loadBytesRaw(File file) throws IOException { static public byte[] loadBytesRaw(File file) throws IOException {
int size = (int) file.length(); int size = (int) file.length();
FileInputStream input = new FileInputStream(file); FileInputStream input = null;
byte buffer[] = new byte[size]; try {
int offset = 0; input = new FileInputStream(file);
int bytesRead; byte buffer[] = new byte[size];
while ((bytesRead = input.read(buffer, offset, size - offset)) != -1) { int offset = 0;
offset += bytesRead; int bytesRead;
if (bytesRead == 0) break; while ((bytesRead = input.read(buffer, offset, size - offset)) != -1) {
offset += bytesRead;
if (bytesRead == 0) break;
}
return buffer;
} finally {
if (input != null) {
input.close();
}
} }
input.close(); // weren't properly being closed
input = null;
return buffer;
} }
@ -2474,20 +2473,25 @@ public class Base {
static public void copyFile(File sourceFile, static public void copyFile(File sourceFile,
File targetFile) throws IOException { File targetFile) throws IOException {
InputStream from = InputStream from = null;
new BufferedInputStream(new FileInputStream(sourceFile)); OutputStream to = null;
OutputStream to = try {
new BufferedOutputStream(new FileOutputStream(targetFile)); from = new BufferedInputStream(new FileInputStream(sourceFile));
byte[] buffer = new byte[16 * 1024]; to = new BufferedOutputStream(new FileOutputStream(targetFile));
int bytesRead; byte[] buffer = new byte[16 * 1024];
while ((bytesRead = from.read(buffer)) != -1) { int bytesRead;
to.write(buffer, 0, bytesRead); while ((bytesRead = from.read(buffer)) != -1) {
to.write(buffer, 0, bytesRead);
}
to.flush();
} finally {
if (from != null) {
from.close(); // ??
}
if (to != null) {
to.close(); // ??
}
} }
to.flush();
from.close(); // ??
from = null;
to.close(); // ??
to = null;
targetFile.setLastModified(sourceFile.lastModified()); targetFile.setLastModified(sourceFile.lastModified());
} }

View File

@ -209,7 +209,7 @@ public class Preferences {
// and linux is all over the map // and linux is all over the map
static final int GUI_BIG = 13; static final int GUI_BIG = 13;
static final int GUI_BETWEEN = 10; static final int GUI_BETWEEN = 5;
static final int GUI_SMALL = 6; static final int GUI_SMALL = 6;
// gui elements // gui elements
@ -237,7 +237,7 @@ public class Preferences {
JTextField proxyHTTPSPort; JTextField proxyHTTPSPort;
JTextField proxyUser; JTextField proxyUser;
JPasswordField proxyPassword; JPasswordField proxyPassword;
private final JTextField additionalBoardsManagerField;
// the calling editor, so updates can be applied // the calling editor, so updates can be applied
@ -464,6 +464,8 @@ public class Preferences {
right = Math.max(right, left + d.width); right = Math.max(right, left + d.width);
top += d.height + GUI_BETWEEN; top += d.height + GUI_BETWEEN;
// proxy settings
JPanel proxySettingsContainer = new JPanel(); JPanel proxySettingsContainer = new JPanel();
pane.add(proxySettingsContainer); pane.add(proxySettingsContainer);
setupProxySettingsFieldSet(proxySettingsContainer); setupProxySettingsFieldSet(proxySettingsContainer);
@ -472,6 +474,17 @@ public class Preferences {
right = Math.max(right, left + d.width); right = Math.max(right, left + d.width);
top += d.height + GUI_BETWEEN; top += d.height + GUI_BETWEEN;
// boards manager additional urls
box = Box.createHorizontalBox();
label = new JLabel(_("Additional Boards Manager URLs: "));
box.add(label);
additionalBoardsManagerField = new JTextField(30);
box.add(additionalBoardsManagerField);
pane.add(box);
d = box.getPreferredSize();
box.setBounds(left, top, d.width, d.height);
top += d.height + GUI_BETWEEN;
// More preferences are in the ... // More preferences are in the ...
label = new JLabel(_("More preferences can be edited directly in the file")); label = new JLabel(_("More preferences can be edited directly in the file"));
@ -788,6 +801,8 @@ public class Preferences {
Preferences.set("proxy.user", proxyUser.getText()); Preferences.set("proxy.user", proxyUser.getText());
Preferences.set("proxy.password", new String(proxyPassword.getPassword())); Preferences.set("proxy.password", new String(proxyPassword.getPassword()));
Preferences.set("boardsmanager.additional.urls", additionalBoardsManagerField.getText().replace("\r\n", "\n").replace("\r", "\n").replace("\n", ","));
editor.applyPreferences(); editor.applyPreferences();
} }
@ -834,6 +849,8 @@ public class Preferences {
proxyUser.setText(Preferences.get("proxy.user")); proxyUser.setText(Preferences.get("proxy.user"));
proxyPassword.setText(Preferences.get("proxy.password")); proxyPassword.setText(Preferences.get("proxy.password"));
additionalBoardsManagerField.setText(Preferences.get("boardsmanager.additional.urls"));
dialog.setLocationRelativeTo(editor); dialog.setLocationRelativeTo(editor);
dialog.setVisible(true); dialog.setVisible(true);
} }

View File

@ -26,6 +26,7 @@ import static processing.app.I18n._;
import java.awt.Color; import java.awt.Color;
import java.awt.Font; import java.awt.Font;
import java.awt.SystemColor; import java.awt.SystemColor;
import java.io.File;
import processing.app.helpers.PreferencesHelper; import processing.app.helpers.PreferencesHelper;
import processing.app.helpers.PreferencesMap; import processing.app.helpers.PreferencesMap;
@ -45,7 +46,7 @@ public class Theme {
static protected void init() { static protected void init() {
try { try {
table.load(Base.getLibStream("theme/theme.txt")); table.load(new File(BaseNoGui.getContentFile("lib"), "theme/theme.txt"));
} catch (Exception te) { } catch (Exception te) {
Base.showError(null, _("Could not read color theme settings.\n" + Base.showError(null, _("Could not read color theme settings.\n" +
"You'll need to reinstall Arduino."), te); "You'll need to reinstall Arduino."), te);

View File

@ -22,16 +22,16 @@
package processing.app; package processing.app;
import processing.app.legacy.PApplet;
import javax.swing.*;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.InputStream; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.URL; import java.net.URL;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Random; import java.util.Random;
import javax.swing.JOptionPane;
import processing.app.legacy.PApplet;
import static processing.app.I18n._; import static processing.app.I18n._;
@ -126,11 +126,16 @@ public class UpdateCheck implements Runnable {
} }
protected int readInt(String filename) throws Exception { protected int readInt(String filename) throws IOException {
URL url = new URL(filename); URL url = new URL(filename);
InputStream stream = url.openStream(); BufferedReader reader = null;
InputStreamReader isr = new InputStreamReader(stream); try {
BufferedReader reader = new BufferedReader(isr); reader = new BufferedReader(new InputStreamReader(url.openStream()));
return Integer.parseInt(reader.readLine()); return Integer.parseInt(reader.readLine());
} finally {
if (reader != null) {
reader.close();
}
}
} }
} }

View File

@ -61,10 +61,10 @@ public class PdeKeywords extends CTokenMarker {
try { try {
keywordColoring = new KeywordMap(false); keywordColoring = new KeywordMap(false);
keywordToReference = new Hashtable(); keywordToReference = new Hashtable();
getKeywords(Base.getLibStream("keywords.txt")); getKeywords(new File(BaseNoGui.getContentFile("lib"), "keywords.txt"));
for (ContributedLibrary lib : Base.getLibraries()) { for (ContributedLibrary lib : Base.getLibraries()) {
File keywords = new File(lib.getInstalledFolder(), "keywords.txt"); File keywords = new File(lib.getInstalledFolder(), "keywords.txt");
if (keywords.exists()) getKeywords(new FileInputStream(keywords)); if (keywords.exists()) getKeywords(keywords);
} }
} catch (Exception e) { } catch (Exception e) {
Base.showError("Problem loading keywords", Base.showError("Problem loading keywords",
@ -76,51 +76,56 @@ public class PdeKeywords extends CTokenMarker {
return keywordColoring; return keywordColoring;
} }
static private void getKeywords(InputStream input) throws Exception { static private void getKeywords(File input) throws IOException {
InputStreamReader isr = new InputStreamReader(input); BufferedReader reader = null;
BufferedReader reader = new BufferedReader(isr); try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(input)));
String line = null; String line = null;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
//System.out.println("line is " + line); //System.out.println("line is " + line);
// in case there's any garbage on the line // in case there's any garbage on the line
//if (line.trim().length() == 0) continue; //if (line.trim().length() == 0) continue;
String pieces[] = PApplet.split(line, '\t'); String pieces[] = PApplet.split(line, '\t');
if (pieces.length >= 2) { if (pieces.length >= 2) {
//int tab = line.indexOf('\t'); //int tab = line.indexOf('\t');
// any line with no tab is ignored // any line with no tab is ignored
// meaning that a comment is any line without a tab // meaning that a comment is any line without a tab
//if (tab == -1) continue; //if (tab == -1) continue;
String keyword = pieces[0].trim(); String keyword = pieces[0].trim();
//String keyword = line.substring(0, tab).trim(); //String keyword = line.substring(0, tab).trim();
//String second = line.substring(tab + 1); //String second = line.substring(tab + 1);
//tab = second.indexOf('\t'); //tab = second.indexOf('\t');
//String coloring = second.substring(0, tab).trim(); //String coloring = second.substring(0, tab).trim();
//String htmlFilename = second.substring(tab + 1).trim(); //String htmlFilename = second.substring(tab + 1).trim();
String coloring = pieces[1].trim(); String coloring = pieces[1].trim();
if (coloring.length() > 0 && Character.isDigit(coloring.charAt(coloring.length() - 1))) { if (coloring.length() > 0 && Character.isDigit(coloring.charAt(coloring.length() - 1))) {
// text will be KEYWORD or LITERAL // text will be KEYWORD or LITERAL
boolean isKey = (coloring.charAt(0) == 'K'); boolean isKey = (coloring.charAt(0) == 'K');
// KEYWORD1 -> 0, KEYWORD2 -> 1, etc // KEYWORD1 -> 0, KEYWORD2 -> 1, etc
int num = coloring.charAt(coloring.length() - 1) - '1'; int num = coloring.charAt(coloring.length() - 1) - '1';
byte id = (byte) byte id = (byte)
((isKey ? Token.KEYWORD1 : Token.LITERAL1) + num); ((isKey ? Token.KEYWORD1 : Token.LITERAL1) + num);
//System.out.println("got " + (isKey ? "keyword" : "literal") + //System.out.println("got " + (isKey ? "keyword" : "literal") +
// (num+1) + " for " + keyword); // (num+1) + " for " + keyword);
keywordColoring.add(keyword, id); keywordColoring.add(keyword, id);
} }
if (pieces.length >= 3) { if (pieces.length >= 3) {
String htmlFilename = pieces[2].trim(); String htmlFilename = pieces[2].trim();
if (htmlFilename.length() > 0) { if (htmlFilename.length() > 0) {
keywordToReference.put(keyword, htmlFilename); keywordToReference.put(keyword, htmlFilename);
}
} }
} }
} }
} finally {
if (reader != null) {
reader.close();
}
} }
reader.close();
} }

View File

@ -0,0 +1,66 @@
/*
* This file is part of Arduino.
*
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package cc.arduino.packages.contributions;
import cc.arduino.contributions.GPGDetachedSignatureVerifier;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class GPGDetachedSignatureVerifierTest {
private GPGDetachedSignatureVerifier GPGDetachedSignatureVerifier;
@Before
public void setUp() throws Exception {
GPGDetachedSignatureVerifier = new GPGDetachedSignatureVerifier();
}
@Test
public void testSignatureSuccessfulVerification() throws Exception {
File signedFile = new File(GPGDetachedSignatureVerifierTest.class.getResource("./package_index.json").getFile());
File sign = new File(GPGDetachedSignatureVerifierTest.class.getResource("./package_index.json.sig").getFile());
File publickKey = new File(GPGDetachedSignatureVerifierTest.class.getResource("./public.gpg.key").getFile());
assertTrue(GPGDetachedSignatureVerifier.verify(signedFile, sign, publickKey));
}
@Test
public void testSignatureFailingVerification() throws Exception {
File fakeSignedFile = File.createTempFile("fakeSigned", "txt");
fakeSignedFile.deleteOnExit();
File sign = new File(GPGDetachedSignatureVerifierTest.class.getResource("./package_index.json.sig").getFile());
File publickKey = new File(GPGDetachedSignatureVerifierTest.class.getResource("./public.gpg.key").getFile());
assertFalse(GPGDetachedSignatureVerifier.verify(fakeSignedFile, sign, publickKey));
}
}

View File

@ -0,0 +1,757 @@
{
"packages": [
{
"name": "arduino",
"maintainer": "Arduino",
"websiteURL": "http://www.arduino.cc/",
"email": "packages@arduino.cc",
"help": {
"online": "http://arduino.cc/en/Reference/HomePage"
},
"platforms": [
{
"name": "Arduino AVR Boards",
"architecture": "avr",
"version": "1.6.2",
"category": "Arduino",
"url": "http://downloads.arduino.cc/cores/avr-1.6.2.tar.bz2",
"archiveFileName": "avr-1.6.2.tar.bz2",
"checksum": "SHA-256:2909a4c6dd6d7497e7e1b5fcaa2f66a100271417510f3a68593b65af8ff78c1c",
"size": "4877442",
"boards": [
{"name": "Arduino Yún"},
{"name": "Arduino Uno"},
{"name": "Arduino Diecimila"},
{"name": "Arduino Nano"},
{"name": "Arduino Mega"},
{"name": "Arduino MegaADK"},
{"name": "Arduino Leonardo"},
{"name": "Arduino Micro"},
{"name": "Arduino Esplora"},
{"name": "Arduino Mini"},
{"name": "Arduino Ethernet"},
{"name": "Arduino Fio"},
{"name": "Arduino BT"},
{"name": "Arduino LilyPadUSB"},
{"name": "Arduino Lilypad"},
{"name": "Arduino Pro"},
{"name": "Arduino ATMegaNG"},
{"name": "Arduino Robot Control"},
{"name": "Arduino Robot Motor"}
],
"toolsDependencies": [
{
"packager": "arduino",
"name": "avr-gcc",
"version": "4.8.1-arduino2"
},
{
"packager": "arduino",
"name": "avrdude",
"version": "6.0.1-arduino2"
}
]
},
{
"name": "Arduino AVR Boards",
"architecture": "avr",
"version": "1.6.3",
"category": "Arduino",
"help": {
"online": "http://arduino.cc/en/Reference/HomePage"
},
"url": "http://downloads.arduino.cc/cores/avr-1.6.3.tar.bz2",
"archiveFileName": "avr-1.6.3.tar.bz2",
"checksum": "SHA-256:c30033ba70cbb2d46ee0901a331b0f83be082f9110eda0464b624fdbb51b3c7b",
"size": "4876816",
"boards": [
{"name": "Arduino Yún"},
{"name": "Arduino Uno"},
{"name": "Arduino Diecimila"},
{"name": "Arduino Nano"},
{"name": "Arduino Mega"},
{"name": "Arduino MegaADK"},
{"name": "Arduino Leonardo"},
{"name": "Arduino Micro"},
{"name": "Arduino Esplora"},
{"name": "Arduino Mini"},
{"name": "Arduino Ethernet"},
{"name": "Arduino Fio"},
{"name": "Arduino BT"},
{"name": "Arduino LilyPadUSB"},
{"name": "Arduino Lilypad"},
{"name": "Arduino Pro"},
{"name": "Arduino ATMegaNG"},
{"name": "Arduino Robot Control"},
{"name": "Arduino Robot Motor"}
],
"toolsDependencies": [
{
"packager": "arduino",
"name": "avr-gcc",
"version": "4.8.1-arduino3"
},
{
"packager": "arduino",
"name": "avrdude",
"version": "6.0.1-arduino3"
}
]
},
{
"name": "Arduino AVR Boards",
"architecture": "avr",
"version": "1.6.4",
"category": "Arduino",
"help": {
"online": "http://arduino.cc/en/Reference/HomePage"
},
"url": "http://downloads.arduino.cc/cores/avr-1.6.4.tar.bz2",
"archiveFileName": "avr-1.6.4.tar.bz2",
"checksum": "SHA-256:8a243410aeded6dbcbc4b134ba10be5c2562d137bfcf3ac97abdc5844933b363",
"size": "4780884",
"boards": [
{"name": "Arduino Yún"},
{"name": "Arduino Uno"},
{"name": "Arduino Diecimila"},
{"name": "Arduino Nano"},
{"name": "Arduino Mega"},
{"name": "Arduino MegaADK"},
{"name": "Arduino Leonardo"},
{"name": "Arduino Micro"},
{"name": "Arduino Esplora"},
{"name": "Arduino Mini"},
{"name": "Arduino Ethernet"},
{"name": "Arduino Fio"},
{"name": "Arduino BT"},
{"name": "Arduino LilyPadUSB"},
{"name": "Arduino Lilypad"},
{"name": "Arduino Pro"},
{"name": "Arduino ATMegaNG"},
{"name": "Arduino Robot Control"},
{"name": "Arduino Robot Motor"}
],
"toolsDependencies": [
{
"packager": "arduino",
"name": "avr-gcc",
"version": "4.8.1-arduino5"
},
{
"packager": "arduino",
"name": "avrdude",
"version": "6.0.1-arduino5"
}
]
},
{
"name": "Arduino AVR Boards",
"architecture": "avr",
"version": "1.6.5",
"category": "Arduino",
"help": {
"online": "http://arduino.cc/en/Reference/HomePage"
},
"url": "http://downloads.arduino.cc/cores/avr-1.6.5.tar.bz2",
"archiveFileName": "avr-1.6.5.tar.bz2",
"checksum": "SHA-256:c72d890aa605add677634c6b25ebc3b2ed9e44c38805b95c47eab17a1ca72db6",
"size": "4876957",
"boards": [
{"name": "Arduino Yún"},
{"name": "Arduino Uno"},
{"name": "Arduino Diecimila"},
{"name": "Arduino Nano"},
{"name": "Arduino Mega"},
{"name": "Arduino MegaADK"},
{"name": "Arduino Leonardo"},
{"name": "Arduino Micro"},
{"name": "Arduino Esplora"},
{"name": "Arduino Mini"},
{"name": "Arduino Ethernet"},
{"name": "Arduino Fio"},
{"name": "Arduino BT"},
{"name": "Arduino LilyPadUSB"},
{"name": "Arduino Lilypad"},
{"name": "Arduino Pro"},
{"name": "Arduino ATMegaNG"},
{"name": "Arduino Robot Control"},
{"name": "Arduino Robot Motor"}
],
"toolsDependencies": [
{
"packager": "arduino",
"name": "avr-gcc",
"version": "4.8.1-arduino5"
},
{
"packager": "arduino",
"name": "avrdude",
"version": "6.0.1-arduino5"
}
]
},
{
"name": "Arduino AVR Boards",
"architecture": "avr",
"version": "1.6.6",
"category": "Arduino",
"help": {
"online": "http://arduino.cc/en/Reference/HomePage"
},
"url": "http://downloads.arduino.cc/cores/avr-1.6.6.tar.bz2",
"archiveFileName": "avr-1.6.6.tar.bz2",
"checksum": "SHA-256:08ad5db4978ebea22344edc5d77dce0923d8a644da7a14dc8072e883c76058d8",
"size": "4876916",
"boards": [
{"name": "Arduino Yún"},
{"name": "Arduino Uno"},
{"name": "Arduino Diecimila"},
{"name": "Arduino Nano"},
{"name": "Arduino Mega"},
{"name": "Arduino MegaADK"},
{"name": "Arduino Leonardo"},
{"name": "Arduino Micro"},
{"name": "Arduino Esplora"},
{"name": "Arduino Mini"},
{"name": "Arduino Ethernet"},
{"name": "Arduino Fio"},
{"name": "Arduino BT"},
{"name": "Arduino LilyPadUSB"},
{"name": "Arduino Lilypad"},
{"name": "Arduino Pro"},
{"name": "Arduino ATMegaNG"},
{"name": "Arduino Robot Control"},
{"name": "Arduino Robot Motor"}
],
"toolsDependencies": [
{
"packager": "arduino",
"name": "avr-gcc",
"version": "4.8.1-arduino5"
},
{
"packager": "arduino",
"name": "avrdude",
"version": "6.0.1-arduino5"
}
]
},
{
"name": "Arduino SAM Boards (32-bits ARM Cortex-M3)",
"architecture": "sam",
"version": "1.6.2",
"category": "Arduino",
"url": "http://downloads.arduino.cc/cores/sam-1.6.2.tar.bz2",
"archiveFileName": "sam-1.6.2.tar.bz2",
"checksum": "SHA-256:2d3c8a90bc214947cff1b816d0c2706441398efc78af7984d5250f2e50eddd5f",
"size": "16174730",
"boards": [
{"name": "Arduino Due"}
],
"toolsDependencies": [
{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
},
{
"packager": "arduino",
"name": "bossac",
"version": "1.3a-arduino"
}
]
},
{
"name": "Arduino SAM Boards (32-bits ARM Cortex-M3)",
"architecture": "sam",
"version": "1.6.3",
"category": "Arduino",
"url": "http://downloads.arduino.cc/cores/sam-1.6.3.tar.bz2",
"archiveFileName": "sam-1.6.3.tar.bz2",
"checksum": "SHA-256:0a6e1d5542790e38ba454c796aabbd0e48b07635a5b4d8adc044a4eba959ca27",
"size": "16174017",
"boards": [
{"name": "Arduino Due"}
],
"toolsDependencies": [
{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
},
{
"packager": "arduino",
"name": "bossac",
"version": "1.3a-arduino"
}
]
},
{
"name": "Arduino SAM Boards (32-bits ARM Cortex-M3)",
"architecture": "sam",
"version": "1.6.4",
"category": "Arduino",
"url": "http://downloads.arduino.cc/cores/sam-1.6.4.tar.bz2",
"archiveFileName": "sam-1.6.4.tar.bz2",
"checksum": "SHA-256:e0dc94d8ad0756b79838e99ad7409b08b07e40ed667ebe86eae11644ef7bec0d",
"size": "16174992",
"boards": [
{"name": "Arduino Due"}
],
"toolsDependencies": [
{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
},
{
"packager": "arduino",
"name": "bossac",
"version": "1.3a-arduino"
}
]
}
],
"tools": [
{
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1",
"systems": [
{
"host": "i686-mingw32",
"archiveFileName": "gcc-arm-none-eabi-4.8.3-2014q1-windows.tar.gz",
"url": "http://downloads.arduino.cc/gcc-arm-none-eabi-4.8.3-2014q1-windows.tar.gz",
"checksum": "SHA-256:fd8c111c861144f932728e00abd3f7d1107e186eb9cd6083a54c7236ea78b7c2",
"size": "84537449"
},
{
"host": "x86_64-apple-darwin",
"url": "http://downloads.arduino.cc/gcc-arm-none-eabi-4.8.3-2014q1-mac.tar.gz",
"archiveFileName": "gcc-arm-none-eabi-4.8.3-2014q1-mac.tar.gz",
"checksum": "SHA-256:3598acf21600f17a8e4a4e8e193dc422b894dc09384759b270b2ece5facb59c2",
"size": "52518522"
},
{
"host": "x86_64-pc-linux-gnu",
"url": "http://downloads.arduino.cc/gcc-arm-none-eabi-4.8.3-2014q1-linux64.tar.gz",
"archiveFileName": "gcc-arm-none-eabi-4.8.3-2014q1-linux64.tar.gz",
"checksum": "SHA-256:d23f6626148396d6ec42a5b4d928955a703e0757829195fa71a939e5b86eecf6",
"size": "51395093"
},
{
"host": "i686-pc-linux-gnu",
"url": "http://downloads.arduino.cc/gcc-arm-none-eabi-4.8.3-2014q1-linux32.tar.gz",
"archiveFileName": "gcc-arm-none-eabi-4.8.3-2014q1-linux32.tar.gz",
"checksum": "SHA-256:ba1994235f69c526c564f65343f22ddbc9822b2ea8c5ee07dd79d89f6ace2498",
"size": "51029223"
}
]
},
{
"name": "bossac",
"version": "1.3a-arduino",
"systems": [
{
"host": "i686-linux-gnu",
"url": "http://downloads.arduino.cc/tools/bossac-1.3a-arduino-i686-linux-gnu.tar.bz2",
"archiveFileName": "bossac-1.3a-arduino-i686-linux-gnu.tar.bz2",
"checksum": "SHA-256:d6d10362f40729a7877e43474fcf02ad82cf83321cc64ca931f5c82b2d25d24f",
"size": "147359"
},
{
"host": "x86_64-pc-linux-gnu",
"url": "http://downloads.arduino.cc/tools/bossac-1.3a-arduino-x86_64-pc-linux-gnu.tar.bz2",
"archiveFileName": "bossac-1.3a-arduino-x86_64-pc-linux-gnu.tar.bz2",
"checksum": "SHA-256:c1daed033251296768fa8b63ad283e053da93427c0f3cd476a71a9188e18442c",
"size": "26179"
},
{
"host": "i686-mingw32",
"url": "http://downloads.arduino.cc/tools/bossac-1.3a-arduino-i686-mingw32.tar.bz2",
"archiveFileName": "bossac-1.3a-arduino-i686-mingw32.tar.bz2",
"checksum": "SHA-256:a37727622e0f86cb4f2856ad0209568a5d804234dba3dc0778829730d61a5ec7",
"size": "265647"
},
{
"host": "i386-apple-darwin11",
"url": "http://downloads.arduino.cc/tools/bossac-1.3a-arduino-i386-apple-darwin11.tar.bz2",
"archiveFileName": "bossac-1.3a-arduino-i386-apple-darwin11.tar.bz2",
"checksum": "SHA-256:40770b225753e7a52bb165e8f37e6b760364f5c5e96048168d0178945bd96ad6",
"size": "39475"
}
]
},
{
"name": "avr-gcc",
"version": "4.8.1-arduino2",
"systems": [
{
"size": "24443285",
"checksum": "SHA-256:c19a7526235c364d7f62ec1a993d9b495973ba1813869ccf0241c65905896852",
"host": "i386-apple-darwin11",
"archiveFileName": "avr-gcc-4.8.1-arduino2-i386-apple-darwin11.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino2-i386-apple-darwin11.tar.bz2"
},
{
"size": "27152002",
"checksum": "SHA-256:24a931877bee5f36dc00a88877219a6d2f6a1fb7abb989fd04556b8432d2e14e",
"host": "x86_64-linux-gnu",
"archiveFileName": "avr-gcc-4.8.1-arduino2-x86_64-pc-linux-gnu.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino2-x86_64-pc-linux-gnu.tar.bz2"
},
{
"size": "25876628",
"checksum": "SHA-256:2d701b4efbc8cec62dc299cde01730c5eebcf23d7e4393db8cf7744a9bf1d3de",
"host": "i686-linux-gnu",
"archiveFileName": "avr-gcc-4.8.1-arduino2-i686-pc-linux-gnu.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino2-i686-pc-linux-gnu.tar.bz2"
},
{
"size": "46046691",
"checksum": "SHA-256:2eafb49fb803fa4d2c32d35e24c0b372fcd520ca0a790fa537a847179e382000",
"host": "i686-mingw32",
"archiveFileName": "avr-gcc-4.8.1-arduino2-i686-mingw32.zip",
"url": "http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino2-i686-mingw32.zip"
}
]
},
{
"name": "avrdude",
"version": "6.0.1-arduino2",
"systems": [
{
"size": "264965",
"checksum": "SHA-256:71117cce0096dad6c091e2c34eb0b9a3386d3aec7d863d2da733d9e5eac3a6b1",
"host": "i386-apple-darwin11",
"archiveFileName": "avrdude-6.0.1-arduino2-i386-apple-darwin11.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avrdude-6.0.1-arduino2-i386-apple-darwin11.tar.bz2"
},
{
"size": "292541",
"checksum": "SHA-256:2489004d1d98177eaf69796760451f89224007c98b39ebb5577a9a34f51425f1",
"host": "x86_64-linux-gnu",
"archiveFileName": "avrdude-6.0.1-arduino2-x86_64-pc-linux-gnu.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avrdude-6.0.1-arduino2-x86_64-pc-linux-gnu.tar.bz2"
},
{
"size": "283209",
"checksum": "SHA-256:6f633dd6270ad0d9ef19507bcbf8697b414a15208e4c0f71deec25ef89cdef3f",
"host": "i686-linux-gnu",
"archiveFileName": "avrdude-6.0.1-arduino2-i686-pc-linux-gnu.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avrdude-6.0.1-arduino2-i686-pc-linux-gnu.tar.bz2"
},
{
"size": "241618",
"checksum": "SHA-256:6c5483800ba753c80893607e30cade8ab77b182808fcc5ea15fa3019c63d76ae",
"host": "i686-mingw32",
"archiveFileName": "avrdude-6.0.1-arduino2-i686-mingw32.zip",
"url": "http://downloads.arduino.cc/tools/avrdude-6.0.1-arduino2-i686-mingw32.zip"
}
]
},
{
"name": "avr-gcc",
"version": "4.8.1-arduino3",
"systems": [
{
"size": "24447175",
"checksum": "SHA-256:28e207c66b3dc405367d0c5e68ce3c278e5ec3abb0e4974e7927fe0f9a532c40",
"host": "i386-apple-darwin11",
"archiveFileName": "avr-gcc-4.8.1-arduino3-i386-apple-darwin11.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino3-i386-apple-darwin11.tar.bz2"
},
{
"size": "30556996",
"checksum": "SHA-256:028340abec6eb3085b82404dfc7ed143e1bb05b2da961b539ddcdba4a6f65533",
"host": "x86_64-linux-gnu",
"archiveFileName": "avr-gcc-4.8.1-arduino3-x86_64-pc-linux-gnu.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino3-x86_64-pc-linux-gnu.tar.bz2"
},
{
"size": "28768022",
"checksum": "SHA-256:37796548ba9653267568f959cd8c7ebfe5b4bce4599898cf9f876d64e616cb87",
"host": "i686-linux-gnu",
"archiveFileName": "avr-gcc-4.8.1-arduino3-i686-pc-linux-gnu.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino3-i686-pc-linux-gnu.tar.bz2"
},
{
"size": "46046917",
"checksum": "SHA-256:d6f0527793f9800f060408392a99eb290ed205730edbae43a1a25cbf6b6b588f",
"host": "i686-mingw32",
"archiveFileName": "avr-gcc-4.8.1-arduino3-i686-mingw32.zip",
"url": "http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino3-i686-mingw32.zip"
}
]
},
{
"name": "avrdude",
"version": "6.0.1-arduino3",
"systems": [
{
"size": "264682",
"checksum": "SHA-256:df7cd4a76e45ab3767eb964f845f4d5e9d643df950ec32812923da1e9843d072",
"host": "i386-apple-darwin11",
"archiveFileName": "avrdude-6.0.1-arduino3-i386-apple-darwin11.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avrdude-6.0.1-arduino3-i386-apple-darwin11.tar.bz2"
},
{
"size": "748634",
"checksum": "SHA-256:bb7bff48f20a68e1fe559c3f3f644574df12ab5c98eb6a1491079f3c760434ad",
"host": "x86_64-linux-gnu",
"archiveFileName": "avrdude-6.0.1-arduino3-x86_64-pc-linux-gnu.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avrdude-6.0.1-arduino3-x86_64-pc-linux-gnu.tar.bz2"
},
{
"size": "495482",
"checksum": "SHA-256:96a0cfb83fe0452366159e3bf4e19ff10906a8957d1feafd3d98b49ab4b14405",
"host": "i686-linux-gnu",
"archiveFileName": "avrdude-6.0.1-arduino3-i686-pc-linux-gnu.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avrdude-6.0.1-arduino3-i686-pc-linux-gnu.tar.bz2"
},
{
"size": "241619",
"checksum": "SHA-256:ea59bfc2ee85039c85318b2ba52c47ef0573513444a785b72f59b22586a950f9",
"host": "i686-mingw32",
"archiveFileName": "avrdude-6.0.1-arduino3-i686-mingw32.zip",
"url": "http://downloads.arduino.cc/tools/avrdude-6.0.1-arduino3-i686-mingw32.zip"
}
]
},
{
"name": "avr-gcc",
"version": "4.8.1-arduino5",
"systems": [
{
"size": "24437400",
"checksum": "SHA-256:111b3ef00d737d069eb237a8933406cbb928e4698689e24663cffef07688a901",
"host": "i386-apple-darwin11",
"archiveFileName": "avr-gcc-4.8.1-arduino5-i386-apple-darwin11.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino5-i386-apple-darwin11.tar.bz2"
},
{
"size": "27093036",
"checksum": "SHA-256:9054fcc174397a419ba56c4ce1bfcbcad275a6a080cc144905acc9b0351ee9cc",
"host": "x86_64-linux-gnu",
"archiveFileName": "avr-gcc-4.8.1-arduino5-x86_64-pc-linux-gnu.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino5-x86_64-pc-linux-gnu.tar.bz2"
},
{
"size": "25882375",
"checksum": "SHA-256:7648b7f549b37191da0b0be53bae791b652f82ac3cb4e7877f85075aaf32141f",
"host": "i686-linux-gnu",
"archiveFileName": "avr-gcc-4.8.1-arduino5-i686-pc-linux-gnu.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino5-i686-pc-linux-gnu.tar.bz2"
},
{
"size": "46044779",
"checksum": "SHA-256:d4303226a7b41d3c445d901b5aa5903458def3fc7b7ff4ffef37cabeb37d424d",
"host": "i686-mingw32",
"archiveFileName": "avr-gcc-4.8.1-arduino5-i686-mingw32.zip",
"url": "http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino5-i686-mingw32.zip"
}
]
},
{
"name": "avrdude",
"version": "6.0.1-arduino5",
"systems": [
{
"size": "264894",
"checksum": "SHA-256:41af8d3b0a586853c8317b4fb5163ca0db594a1870ddf680fd988c42166fc3e5",
"host": "i386-apple-darwin11",
"archiveFileName": "avrdude-6.0.1-arduino5-i386-apple-darwin11.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avrdude-6.0.1-arduino5-i386-apple-darwin11.tar.bz2"
},
{
"size": "292629",
"checksum": "SHA-256:d826cca7383461f7e8adde686372cf900e9cb3afd639555cf2d6c645b283a476",
"host": "x86_64-linux-gnu",
"archiveFileName": "avrdude-6.0.1-arduino5-x86_64-pc-linux-gnu.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avrdude-6.0.1-arduino5-x86_64-pc-linux-gnu.tar.bz2"
},
{
"size": "283121",
"checksum": "SHA-256:5933d66927bce46ababa9b68a8b7f1d53f68c4f3ff7a5ce4b85d7cf4e6c6bfee",
"host": "i686-linux-gnu",
"archiveFileName": "avrdude-6.0.1-arduino5-i686-pc-linux-gnu.tar.bz2",
"url": "http://downloads.arduino.cc/tools/avrdude-6.0.1-arduino5-i686-pc-linux-gnu.tar.bz2"
},
{
"size": "241634",
"checksum": "SHA-256:41f667f1f6a0ab8df46b4ffacd023176dcdef331d6db3b74bddd37d18cca0a44",
"host": "i686-mingw32",
"archiveFileName": "avrdude-6.0.1-arduino5-i686-mingw32.zip",
"url": "http://downloads.arduino.cc/tools/avrdude-6.0.1-arduino5-i686-mingw32.zip"
}
]
}
]
},
{
"email": "support@intel.com",
"maintainer": "Intel",
"websiteURL": "http://www.intel.com/",
"name": "Intel",
"platforms": [
{
"name": "Intel i586 Boards",
"version": "1.6.2+1.0",
"category": "Arduino Certified",
"architecture": "i586",
"url": "https://github.com/01org/corelibs-galileo/archive/1.6.2+1.0.tar.gz",
"archiveFileName": "corelibs-galileo-1.6.2.tar.gz",
"checksum": "SHA-256:e20d62b0dccf0d68dbb61d70b866d77134b770b226d6046a61c7e8d55e64e53a",
"size": "272961",
"boards": [
{
"name": "Galileo"
}
],
"toolsDependencies": [
{
"packager": "Intel",
"name": "i586-poky-linux-uclibc",
"version": "1.6.2+1.0"
},
{
"packager": "Intel",
"name": "sketchUploader",
"version": "1.6.2+1.0"
}
]
},
{
"name": "Intel i686 Boards",
"version": "1.6.2+1.0",
"category": "Arduino Certified",
"architecture": "i686",
"url": "https://github.com/01org/corelibs-edison/archive/1.6.2+1.0.tar.gz",
"archiveFileName": "corelibs-edison-1.6.2.tar.gz",
"checksum": "SHA-256:538ab8553f832f56b04df80d44992ecc994b9c296f3fce6902832d97f99811a8",
"size": "271420",
"boards": [
{
"name": "Edison"
}
],
"toolsDependencies": [
{
"packager": "Intel",
"name": "core2-32-poky-linux",
"version": "1.6.2+1.0"
},
{
"packager": "Intel",
"name": "sketchUploader",
"version": "1.6.2+1.0"
}
]
}
],
"tools": [
{
"name": "i586-poky-linux-uclibc",
"version": "1.6.2+1.0",
"systems": [
{
"size": "30587705",
"checksum": "SHA-256:5b705d26dc1d8ca8953df6e0c08dcc8584d5be77b584d561f631360fd166677c",
"host": "i386-apple-darwin11",
"archiveFileName": "galileo-toolchain-20150323-osx.tar.bz2",
"url": "http://downloadmirror.intel.com/24806/eng/galileo-toolchain-osx-1.6.2-1.0.tar.bz2"
},
{
"size": "45948648",
"checksum": "SHA-256:821eb290d7c668c1caa74da30903c13843edc746d41508b35161622ae6279b56",
"host": "i686-mingw32",
"archiveFileName": "galileo-toolchain-20150323-windows.zip",
"url": "http://downloadmirror.intel.com/24806/eng/galileo-toolchain-windows-1.6.2-1.0.zip"
},
{
"size": "56227185",
"checksum": "SHA-256:935ccad3eaaec34f5de76eceb0f0ecd1372bdab0b7dc8f4241e8260c6f827b72",
"host": "x86_64-linux-gnu",
"archiveFileName": "galileo-toolchain-20150316-linux64.tar.bz2",
"url": "http://downloadmirror.intel.com/24806/eng/galileo-toolchain-linux64-1.6.2-1.0.tar.bz2"
},
{
"size": "55098166",
"checksum": "SHA-256:1dab7f21e10d0208a6dd2897c36c6f5f55f9372b947225d2b59c3c4ab4777d03",
"host": "i686-linux-gnu",
"archiveFileName": "galileo-toolchain-20150316-linux32.tar.bz2",
"url": "http://downloadmirror.intel.com/24806/eng/galileo-toolchain-linux32-1.6.2-1.0.tar.bz2"
}
]
},
{
"name": "core2-32-poky-linux",
"version": "1.6.2+1.0",
"systems": [
{
"size": "42720934",
"checksum": "SHA-256:fac0b3f00a33ee0531ea0da6d517c170409e25bd5e59f6f3db9506974336375d",
"host": "i386-apple-darwin11",
"archiveFileName": "edison-toolchain-20150323-osx.tar.bz2",
"url": "http://downloadmirror.intel.com/24806/eng/edison-toolchain-osx-1.6.2-1.0.tar.bz2"
},
{
"size": "56683094",
"checksum": "SHA-256:5a9a1b51f0fa18bf21e1dcf1332d34331dd435c5ca0d1fe008e68e13cb3255e5",
"host": "i686-mingw32",
"archiveFileName": "edison-toolchain-20150323-windows.zip",
"url": "http://downloadmirror.intel.com/24806/eng/edison-toolchain-windows-1.6.2-1.0.zip"
},
{
"size": "78998436",
"checksum": "SHA-256:e3443e7832732f2189fd424e4868d2ebb563e823addb2321a6e8a86a9fced193",
"host": "x86_64-linux-gnu",
"archiveFileName": "edison-toolchain-20150316-linux64.tar.bz2",
"url": "http://downloadmirror.intel.com/24806/eng/edison-toolchain-linux64-1.6.2-1.0.tar.bz2"
},
{
"size": "76488215",
"checksum": "SHA-256:014d1bdc40bb080987c736d04ffd42cdc0d2c3cad001891fb01555dac04296f7",
"host": "i686-linux-gnu",
"archiveFileName": "edison-toolchain-20150316-linux32.tar.bz2",
"url": "http://downloadmirror.intel.com/24806/eng/edison-toolchain-linux32-1.6.2-1.0.tar.bz2"
}
]
},
{
"name": "sketchUploader",
"version": "1.6.2+1.0",
"systems": [
{
"size": "61789",
"checksum": "SHA-256:8395ccb57c627f997fe01170df4613de906f48c6ce99623b9ca42806079c28ad",
"host": "i386-apple-darwin11",
"archiveFileName": "intel-arduino-tools-20150316-osx.tar.gz",
"url": "https://github.com/01org/intel-arduino-tools/archive/1.6.2+1.0-osx.tar.gz"
},
{
"size": "2534586",
"checksum": "SHA-256:47f0b1558653d09f6f1e5d21a9cdef379be96c9147711cf54f013f73e4deed11",
"host": "i686-mingw32",
"archiveFileName": "intel-arduino-tools-20150316-windows.zip",
"url": "https://github.com/01org/intel-arduino-tools/archive/1.6.2+1.0-windows.zip"
},
{
"size": "178239",
"checksum": "SHA-256:2876db4153db22609d2f6c9c3bfb198efbb9d9574edad579aca7d58cff9d2cca",
"host": "x86_64-linux-gnu",
"archiveFileName": "intel-arduino-tools-20150316-linux64.tar.gz",
"url": "https://github.com/01org/intel-arduino-tools/archive/1.6.2+1.0-linux64.tar.gz"
},
{
"size": "187995",
"checksum": "SHA-256:20d87602d0194be626f592d3f2bdc9566a5a897786b042393482ef4c26ae158c",
"host": "i686-linux-gnu",
"archiveFileName": "intel-arduino-tools-20150316-linux32.tar.gz",
"url": "https://github.com/01org/intel-arduino-tools/archive/1.6.2+1.0-linux32.tar.gz"
}
]
}
]
}
]
}

View File

@ -17,10 +17,10 @@
<classpathentry kind="lib" path="../app/lib/jackson-core-2.2.3.jar"/> <classpathentry kind="lib" path="../app/lib/jackson-core-2.2.3.jar"/>
<classpathentry kind="lib" path="../app/lib/jackson-databind-2.2.3.jar"/> <classpathentry kind="lib" path="../app/lib/jackson-databind-2.2.3.jar"/>
<classpathentry kind="lib" path="../app/lib/jackson-module-mrbean-2.2.3.jar"/> <classpathentry kind="lib" path="../app/lib/jackson-module-mrbean-2.2.3.jar"/>
<classpathentry kind="lib" path="../app/lib/bcpg-jdk15on-149.jar"/> <classpathentry kind="lib" path="../app/lib/bcpg-jdk15on-152.jar"/>
<classpathentry kind="lib" path="../app/lib/bcprov-jdk15on-149.jar"/> <classpathentry kind="lib" path="../app/lib/bcprov-jdk15on-152.jar"/>
<classpathentry kind="lib" path="lib/bcpg-jdk15on-149.jar"/> <classpathentry kind="lib" path="lib/bcpg-jdk15on-152.jar"/>
<classpathentry kind="lib" path="lib/bcprov-jdk15on-149.jar"/> <classpathentry kind="lib" path="lib/bcprov-jdk15on-152.jar"/>
<classpathentry kind="lib" path="lib/commons-codec-1.7.jar"/> <classpathentry kind="lib" path="lib/commons-codec-1.7.jar"/>
<classpathentry kind="lib" path="lib/commons-compress-1.8.jar"/> <classpathentry kind="lib" path="lib/commons-compress-1.8.jar"/>
<classpathentry kind="lib" path="lib/commons-lang3-3.3.2.jar"/> <classpathentry kind="lib" path="lib/commons-lang3-3.3.2.jar"/>

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,112 @@
/*
* This file is part of Arduino.
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
*/
package cc.arduino.contributions;
import org.apache.commons.compress.utils.IOUtils;
import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider;
import java.io.*;
import java.util.Iterator;
public class GPGDetachedSignatureVerifier {
private String keyId;
public GPGDetachedSignatureVerifier() {
this("7F294291");
}
public GPGDetachedSignatureVerifier(String keyId) {
this.keyId = keyId;
}
public boolean verify(File signedFile, File signature, File publicKey) throws IOException, PGPException {
PGPPublicKey pgpPublicKey = readPublicKey(publicKey, keyId);
FileInputStream signatureInputStream = null;
FileInputStream signedFileInputStream = null;
try {
signatureInputStream = new FileInputStream(signature);
PGPObjectFactory pgpObjectFactory = new PGPObjectFactory(signatureInputStream, new BcKeyFingerprintCalculator());
PGPSignatureList pgpSignatureList = (PGPSignatureList) pgpObjectFactory.nextObject();
assert pgpSignatureList.size() == 1;
PGPSignature pgpSignature = pgpSignatureList.get(0);
pgpSignature.init(new BcPGPContentVerifierBuilderProvider(), pgpPublicKey);
signedFileInputStream = new FileInputStream(signedFile);
pgpSignature.update(IOUtils.toByteArray(signedFileInputStream));
return pgpSignature.verify();
} finally {
if (signatureInputStream != null) {
signatureInputStream.close();
}
if (signedFileInputStream != null) {
signedFileInputStream.close();
}
}
}
private PGPPublicKey readPublicKey(File file, String keyId) throws IOException, PGPException {
InputStream keyIn = null;
try {
keyIn = new BufferedInputStream(new FileInputStream(file));
return readPublicKey(keyIn, keyId);
} finally {
if (keyIn != null) {
keyIn.close();
}
}
}
private PGPPublicKey readPublicKey(InputStream input, String keyId) throws IOException, PGPException {
PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(input), new BcKeyFingerprintCalculator());
Iterator keyRingIter = pgpPub.getKeyRings();
while (keyRingIter.hasNext()) {
PGPPublicKeyRing keyRing = (PGPPublicKeyRing) keyRingIter.next();
Iterator keyIter = keyRing.getPublicKeys();
while (keyIter.hasNext()) {
PGPPublicKey key = (PGPPublicKey) keyIter.next();
if (Long.toHexString(key.getKeyID()).toUpperCase().endsWith(keyId)) {
return key;
}
}
}
throw new IllegalArgumentException("Can't find encryption key in key ring.");
}
}

View File

@ -0,0 +1,16 @@
package cc.arduino.contributions;
import processing.app.I18n;
import static processing.app.I18n._;
public class SignatureVerificationFailedException extends Exception {
public SignatureVerificationFailedException(String filename) {
super(I18n.format(_("{0} file signature verification failed"), filename));
}
public SignatureVerificationFailedException(String filename, Throwable cause) {
super(I18n.format(_("{0} file signature verification failed"), filename), cause);
}
}

View File

@ -70,17 +70,24 @@ public class LibrariesIndexer {
} }
private void parseIndex(File indexFile) throws IOException { private void parseIndex(File indexFile) throws IOException {
InputStream indexIn = new FileInputStream(indexFile); InputStream indexIn = null;
ObjectMapper mapper = new ObjectMapper(); try {
mapper.registerModule(new MrBeanModule()); indexIn = new FileInputStream(indexFile);
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.EAGER_DESERIALIZER_FETCH, true); mapper.registerModule(new MrBeanModule());
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
index = mapper.readValue(indexIn, LibrariesIndex.class); mapper.configure(DeserializationFeature.EAGER_DESERIALIZER_FETCH, true);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
index = mapper.readValue(indexIn, LibrariesIndex.class);
for (ContributedLibrary library : index.getLibraries()) { for (ContributedLibrary library : index.getLibraries()) {
if (library.getCategory() == null || "".equals(library.getCategory())) { if (library.getCategory() == null || "".equals(library.getCategory())) {
library.setCategory("Uncategorized"); library.setCategory("Uncategorized");
}
}
} finally {
if (indexIn != null) {
indexIn.close();
} }
} }
} }

View File

@ -0,0 +1,23 @@
package cc.arduino.contributions.packages;
import java.util.Arrays;
import java.util.List;
public class Constants {
public static final String DEFAULT_INDEX_FILE_NAME = "package_index.json";
public static final List<String> PROTECTED_PACKAGE_NAMES = Arrays.asList("arduino", "Intel");
public static final String PACKAGE_INDEX_URL;
public static final String PREFERENCES_BOARDS_MANAGER_ADDITIONAL_URLS = "boardsmanager.additional.urls";
static {
String extenalPackageIndexUrl = System.getProperty("PACKAGE_INDEX_URL");
if (extenalPackageIndexUrl != null && !"".equals(extenalPackageIndexUrl)) {
PACKAGE_INDEX_URL = extenalPackageIndexUrl;
} else {
PACKAGE_INDEX_URL = "http://downloads.arduino.cc/packages/package_index.json";
}
}
}

View File

@ -39,6 +39,8 @@ public abstract class ContributedPlatform extends DownloadableContribution {
public abstract String getCategory(); public abstract String getCategory();
public abstract void setCategory(String category);
public abstract String getArchitecture(); public abstract String getArchitecture();
public abstract String getChecksum(); public abstract String getChecksum();

View File

@ -28,6 +28,7 @@
*/ */
package cc.arduino.contributions.packages; package cc.arduino.contributions.packages;
import cc.arduino.contributions.GPGDetachedSignatureVerifier;
import cc.arduino.utils.ArchiveExtractor; import cc.arduino.utils.ArchiveExtractor;
import cc.arduino.utils.MultiStepProgress; import cc.arduino.utils.MultiStepProgress;
import cc.arduino.utils.Progress; import cc.arduino.utils.Progress;
@ -36,6 +37,8 @@ import com.google.common.collect.Collections2;
import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.Executor; import org.apache.commons.exec.Executor;
import processing.app.BaseNoGui; import processing.app.BaseNoGui;
import processing.app.I18n;
import processing.app.PreferencesData;
import processing.app.helpers.FileUtils; import processing.app.helpers.FileUtils;
import processing.app.helpers.filefilters.OnlyDirs; import processing.app.helpers.filefilters.OnlyDirs;
import processing.app.tools.CollectStdOutStdErrExecutor; import processing.app.tools.CollectStdOutStdErrExecutor;
@ -44,27 +47,13 @@ import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.Collection; import java.util.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import static processing.app.I18n._; import static processing.app.I18n._;
import static processing.app.I18n.format; import static processing.app.I18n.format;
public class ContributionInstaller { public class ContributionInstaller {
private static final String PACKAGE_INDEX_URL;
static {
String extenalPackageIndexUrl = System.getProperty("PACKAGE_INDEX_URL");
if (extenalPackageIndexUrl != null && !"".equals(extenalPackageIndexUrl)) {
PACKAGE_INDEX_URL = extenalPackageIndexUrl;
} else {
PACKAGE_INDEX_URL = "http://downloads.arduino.cc/packages/package_index.json";
}
}
private final ContributionsIndexer indexer; private final ContributionsIndexer indexer;
private final DownloadableContributionsDownloader downloader; private final DownloadableContributionsDownloader downloader;
@ -239,29 +228,80 @@ public class ContributionInstaller {
} }
public List<String> updateIndex() throws Exception { public List<String> updateIndex() throws Exception {
List<String> errors = new LinkedList<String>();
MultiStepProgress progress = new MultiStepProgress(1); MultiStepProgress progress = new MultiStepProgress(1);
String statusText = _("Downloading platforms index...");
URL url = new URL(PACKAGE_INDEX_URL); List<String> downloadedPackageIndexFilesAccumulator = new LinkedList<String>();
File outputFile = indexer.getIndexFile(); downloadIndexAndSignature(progress, downloadedPackageIndexFilesAccumulator, Constants.PACKAGE_INDEX_URL);
File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp");
downloader.download(url, tmpFile, progress, statusText); Set<String> packageIndexURLs = new HashSet<String>();
String additionalURLs = PreferencesData.get(Constants.PREFERENCES_BOARDS_MANAGER_ADDITIONAL_URLS, "");
if (!"".equals(additionalURLs)) {
packageIndexURLs.addAll(Arrays.asList(additionalURLs.split(",")));
}
for (String packageIndexURL : packageIndexURLs) {
downloadIndexAndSignature(progress, downloadedPackageIndexFilesAccumulator, packageIndexURL);
}
progress.stepDone(); progress.stepDone();
// TODO: Check downloaded index return downloadedPackageIndexFilesAccumulator;
}
private void downloadIndexAndSignature(MultiStepProgress progress, List<String> downloadedPackagedIndexFilesAccumulator, String packageIndexUrl) throws Exception {
File packageIndex = download(progress, packageIndexUrl);
downloadedPackagedIndexFilesAccumulator.add(packageIndex.getName());
try {
File packageIndexSignature = download(progress, packageIndexUrl + ".sig");
boolean signatureVerified = new GPGDetachedSignatureVerifier().verify(packageIndex, packageIndexSignature, new File(BaseNoGui.getContentFile("lib"), "public.gpg.key"));
if (signatureVerified) {
downloadedPackagedIndexFilesAccumulator.add(packageIndexSignature.getName());
} else {
downloadedPackagedIndexFilesAccumulator.remove(packageIndex.getName());
packageIndex.delete();
packageIndexSignature.delete();
System.err.println(I18n.format(_("{0} file signature verification failed. File ignored."), packageIndexUrl));
}
} catch (Exception e) {
//ignore errors
}
}
private File download(MultiStepProgress progress, String packageIndexUrl) throws Exception {
String statusText = _("Downloading platforms index...");
URL url = new URL(packageIndexUrl);
String[] urlPathParts = url.getFile().split("/");
File outputFile = indexer.getIndexFile(urlPathParts[urlPathParts.length - 1]);
File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp");
downloader.download(url, tmpFile, progress, statusText);
// Replace old index with the updated one // Replace old index with the updated one
if (outputFile.exists()) { if (outputFile.exists()) {
outputFile.delete(); if (!outputFile.delete()) {
throw new Exception("An error occurred while updating platforms index! I can't delete file " + outputFile);
}
} }
if (!tmpFile.renameTo(outputFile)) { if (!tmpFile.renameTo(outputFile)) {
throw new Exception("An error occurred while updating platforms index!"); throw new Exception("An error occurred while updating platforms index! I can't rename file " + tmpFile);
} }
return errors;
return outputFile;
} }
protected void onProgress(Progress progress) { protected void onProgress(Progress progress) {
// Empty // Empty
} }
public void deleteUnknownFiles(List<String> downloadedPackageIndexFiles) {
File preferencesFolder = indexer.getIndexFile(".").getParentFile();
File[] additionalPackageIndexFiles = preferencesFolder.listFiles(new PackageIndexFilenameFilter(Constants.DEFAULT_INDEX_FILE_NAME));
if (additionalPackageIndexFiles == null) {
return;
}
for (File additionalPackageIndexFile : additionalPackageIndexFiles) {
if (!downloadedPackageIndexFiles.contains(additionalPackageIndexFile.getName())) {
additionalPackageIndexFile.delete();
}
}
}
} }

View File

@ -137,10 +137,12 @@ public abstract class ContributionsIndex {
} }
} }
public ContributedPackage getPackage(String packager) { public ContributedPackage getPackage(String packageName) {
for (ContributedPackage pack : getPackages()) for (ContributedPackage pack : getPackages()) {
if (pack.getName().equals(packager)) if (pack.getName().equals(packageName)) {
return pack; return pack;
}
}
return null; return null;
} }

View File

@ -29,6 +29,8 @@
package cc.arduino.contributions.packages; package cc.arduino.contributions.packages;
import cc.arduino.contributions.DownloadableContributionBuiltInAtTheBottomComparator; import cc.arduino.contributions.DownloadableContributionBuiltInAtTheBottomComparator;
import cc.arduino.contributions.GPGDetachedSignatureVerifier;
import cc.arduino.contributions.SignatureVerificationFailedException;
import cc.arduino.contributions.filters.BuiltInPredicate; import cc.arduino.contributions.filters.BuiltInPredicate;
import cc.arduino.contributions.filters.InstalledPredicate; import cc.arduino.contributions.filters.InstalledPredicate;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
@ -39,6 +41,7 @@ import com.google.common.base.Predicates;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Multimaps; import com.google.common.collect.Multimaps;
import processing.app.BaseNoGui;
import processing.app.debug.TargetPackage; import processing.app.debug.TargetPackage;
import processing.app.debug.TargetPlatform; import processing.app.debug.TargetPlatform;
import processing.app.debug.TargetPlatformException; import processing.app.debug.TargetPlatformException;
@ -56,33 +59,28 @@ public class ContributionsIndexer {
private final File packagesFolder; private final File packagesFolder;
private final File stagingFolder; private final File stagingFolder;
private final File indexFile; private final File preferencesFolder;
private ContributionsIndex index; private ContributionsIndex index;
public ContributionsIndexer(File preferencesFolder) { public ContributionsIndexer(File preferencesFolder) {
this.preferencesFolder = preferencesFolder;
packagesFolder = new File(preferencesFolder, "packages"); packagesFolder = new File(preferencesFolder, "packages");
stagingFolder = new File(preferencesFolder, "staging" + File.separator + stagingFolder = new File(preferencesFolder, "staging" + File.separator + "packages");
"packages");
indexFile = new File(preferencesFolder, "package_index.json");
} }
// public static void main(String args[]) throws Exception { public void parseIndex() throws Exception {
// File indexFile = new File(args[0]); File defaultIndexFile = getIndexFile(Constants.DEFAULT_INDEX_FILE_NAME);
// if (!isSigned(defaultIndexFile)) {
// // VerifyResult verify = ClearSignedVerifier.verify(indexFile, throw new SignatureVerificationFailedException(Constants.DEFAULT_INDEX_FILE_NAME);
// // new PackagersPublicKeys()); }
// // if (!verify.verified) index = parseIndex(defaultIndexFile);
// // throw new Exception("Invalid index file!");
//
// ContributionsIndexer indexer = new ContributionsIndexer(null);
// // indexer.parse(new ByteArrayInputStream(verify.clearText));
// indexer.parseIndex(indexFile);
// indexer.syncWithFilesystem();
// }
public void parseIndex() throws IOException { File[] indexFiles = preferencesFolder.listFiles(new TestPackageIndexFilenameFilter(new PackageIndexFilenameFilter(Constants.DEFAULT_INDEX_FILE_NAME)));
// Parse index file
parseIndex(indexFile); for (File indexFile : indexFiles) {
ContributionsIndex contributionsIndex = parseIndex(indexFile);
mergeContributions(contributionsIndex, indexFile);
}
List<ContributedPackage> packages = index.getPackages(); List<ContributedPackage> packages = index.getPackages();
for (ContributedPackage pack : packages) { for (ContributedPackage pack : packages) {
@ -98,14 +96,82 @@ public class ContributionsIndexer {
index.fillCategories(); index.fillCategories();
} }
private void parseIndex(File indexFile) throws IOException { private void mergeContributions(ContributionsIndex contributionsIndex, File indexFile) {
InputStream indexIn = new FileInputStream(indexFile); boolean signed = isSigned(indexFile);
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new MrBeanModule()); for (ContributedPackage contributedPackage : contributionsIndex.getPackages()) {
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); if (!signed) {
mapper.configure(DeserializationFeature.EAGER_DESERIALIZER_FETCH, true); for (ContributedPlatform contributedPlatform : contributedPackage.getPlatforms()) {
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); contributedPlatform.setCategory("Contributed");
index = mapper.readValue(indexIn, ContributionsIndex.class); }
}
ContributedPackage targetPackage = index.getPackage(contributedPackage.getName());
if (targetPackage == null) {
index.getPackages().add(contributedPackage);
} else {
if (signed || !isPackageNameProtected(contributedPackage)) {
List<ContributedPlatform> platforms = contributedPackage.getPlatforms();
if (platforms == null) {
platforms = new LinkedList<ContributedPlatform>();
}
for (ContributedPlatform contributedPlatform : platforms) {
ContributedPlatform platform = targetPackage.findPlatform(contributedPlatform.getArchitecture(), contributedPlatform.getVersion());
if (platform != null) {
targetPackage.getPlatforms().remove(platform);
}
targetPackage.getPlatforms().add(contributedPlatform);
}
List<ContributedTool> tools = contributedPackage.getTools();
if (tools == null) {
tools = new LinkedList<ContributedTool>();
}
for (ContributedTool contributedTool : tools) {
ContributedTool tool = targetPackage.findTool(contributedTool.getName(), contributedTool.getVersion());
if (tool != null) {
targetPackage.getTools().remove(tool);
}
targetPackage.getTools().add(contributedTool);
}
}
}
}
}
private boolean isPackageNameProtected(ContributedPackage contributedPackage) {
return Constants.PROTECTED_PACKAGE_NAMES.contains(contributedPackage.getName());
}
private boolean isSigned(File indexFile) {
File signature = new File(indexFile.getParent(), indexFile.getName() + ".sig");
if (!signature.exists()) {
return false;
}
try {
return new GPGDetachedSignatureVerifier().verify(indexFile, signature, new File(BaseNoGui.getContentFile("lib"), "public.gpg.key"));
} catch (Exception e) {
BaseNoGui.showWarning(e.getMessage(), e.getMessage(), e);
return false;
}
}
private ContributionsIndex parseIndex(File indexFile) throws IOException {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(indexFile);
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new MrBeanModule());
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
mapper.configure(DeserializationFeature.EAGER_DESERIALIZER_FETCH, true);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return mapper.readValue(inputStream, ContributionsIndex.class);
} finally {
if (inputStream != null) {
inputStream.close();
}
}
} }
public void syncWithFilesystem(File hardwareFolder) throws IOException { public void syncWithFilesystem(File hardwareFolder) throws IOException {
@ -115,6 +181,9 @@ public class ContributionsIndexer {
} }
public void syncBuiltInHardwareFolder(File hardwareFolder) throws IOException { public void syncBuiltInHardwareFolder(File hardwareFolder) throws IOException {
if (index == null) {
return;
}
for (File folder : hardwareFolder.listFiles(ONLY_DIRS)) { for (File folder : hardwareFolder.listFiles(ONLY_DIRS)) {
ContributedPackage pack = index.findPackage(folder.getName()); ContributedPackage pack = index.findPackage(folder.getName());
if (pack != null) { if (pack != null) {
@ -149,8 +218,13 @@ public class ContributionsIndexer {
} }
public void syncLocalPackagesFolder() { public void syncLocalPackagesFolder() {
if (!packagesFolder.isDirectory()) if (!packagesFolder.isDirectory()) {
return; return;
}
if (index == null) {
return;
}
// Scan all hardware folders and mark as installed all the // Scan all hardware folders and mark as installed all the
// platforms found. // platforms found.
@ -216,6 +290,10 @@ public class ContributionsIndexer {
public List<TargetPackage> createTargetPackages() throws TargetPlatformException { public List<TargetPackage> createTargetPackages() throws TargetPlatformException {
List<TargetPackage> packages = new ArrayList<TargetPackage>(); List<TargetPackage> packages = new ArrayList<TargetPackage>();
if (index == null) {
return packages;
}
for (ContributedPackage aPackage : index.getPackages()) { for (ContributedPackage aPackage : index.getPackages()) {
ContributedTargetPackage targetPackage = new ContributedTargetPackage(aPackage.getName()); ContributedTargetPackage targetPackage = new ContributedTargetPackage(aPackage.getName());
@ -261,6 +339,9 @@ public class ContributionsIndexer {
public Set<ContributedTool> getInstalledTools() { public Set<ContributedTool> getInstalledTools() {
Set<ContributedTool> tools = new HashSet<ContributedTool>(); Set<ContributedTool> tools = new HashSet<ContributedTool>();
if (index == null) {
return tools;
}
for (ContributedPackage pack : index.getPackages()) { for (ContributedPackage pack : index.getPackages()) {
Collection<ContributedPlatform> platforms = Collections2.filter(pack.getPlatforms(), new InstalledPredicate()); Collection<ContributedPlatform> platforms = Collections2.filter(pack.getPlatforms(), new InstalledPredicate());
ImmutableListMultimap<String, ContributedPlatform> platformsByName = Multimaps.index(platforms, new Function<ContributedPlatform, String>() { ImmutableListMultimap<String, ContributedPlatform> platformsByName = Multimaps.index(platforms, new Function<ContributedPlatform, String>() {
@ -295,8 +376,28 @@ public class ContributionsIndexer {
return stagingFolder; return stagingFolder;
} }
public File getIndexFile() { public File getIndexFile(String name) {
return indexFile; return new File(preferencesFolder, name);
} }
public List<ContributedPackage> getPackages() {
if (index == null) {
return new LinkedList<ContributedPackage>();
}
return index.getPackages();
}
public List<String> getCategories() {
if (index == null) {
return new LinkedList<String>();
}
return index.getCategories();
}
public ContributedPlatform getInstalled(String packageName, String platformArch) {
if (index == null) {
return null;
}
return index.getInstalled(packageName, platformArch);
}
} }

View File

@ -0,0 +1,18 @@
package cc.arduino.contributions.packages;
import java.io.File;
import java.io.FilenameFilter;
public class PackageIndexFilenameFilter implements FilenameFilter {
private final String defaultPackageIndexFileName;
public PackageIndexFilenameFilter(String defaultPackageIndexFileName) {
this.defaultPackageIndexFileName = defaultPackageIndexFileName;
}
@Override
public boolean accept(File file, String name) {
return new File(file, name).isFile() && !defaultPackageIndexFileName.equals(name) && name.startsWith("package_") && name.endsWith("_index.json");
}
}

View File

@ -0,0 +1,27 @@
package cc.arduino.contributions.packages;
import java.io.File;
import java.io.FilenameFilter;
public class TestPackageIndexFilenameFilter implements FilenameFilter {
private final FilenameFilter parent;
public TestPackageIndexFilenameFilter(FilenameFilter parent) {
this.parent = parent;
}
public TestPackageIndexFilenameFilter() {
this(null);
}
@Override
public boolean accept(File file, String name) {
boolean result = false;
if (parent != null) {
result = parent.accept(file, name);
}
result = result || (new File(file, name).isFile() && name.startsWith("test_package_") && name.endsWith("_index.json"));
return result;
}
}

View File

@ -1,135 +0,0 @@
/*
* This file is part of Arduino.
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*
* Copyright 2013 Arduino LLC (http://www.arduino.cc/)
*/
package cc.arduino.packages.security;
import cc.arduino.packages.security.keys.PackagersPublicKeys;
import org.bouncycastle.bcpg.ArmoredInputStream;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
import processing.app.helpers.StringUtils;
import java.io.*;
import java.security.Security;
public class ClearSignedVerifier {
public static class VerifyResult {
public byte clearText[];
public boolean verified;
public Exception error;
}
/**
* Verify a PGP clearText-signature.
*
* @param signedTextFile A File containing the clearText signature
* @param pubKeyRing A public key-ring containing the public key needed for the
* signature verification
* @return A VerifyResult class with the clearText and the signature
* verification status
* @throws FileNotFoundException
*/
public static VerifyResult verify(File signedTextFile,
PGPPublicKeyRingCollection pubKeyRing) {
// Create the result object
VerifyResult result = new VerifyResult();
result.clearText = null;
result.verified = false;
result.error = null;
ArmoredInputStream in = null;
try {
// Extract clear text.
// Dash-encoding is removed by ArmoredInputStream.
in = new ArmoredInputStream(new FileInputStream(signedTextFile));
ByteArrayOutputStream temp = new ByteArrayOutputStream(in.available());
while (true) {
int c = in.read();
if (c == -1)
throw new IOException("Unexpected end of file");
if (!in.isClearText())
break;
temp.write(c);
}
byte clearText[] = temp.toByteArray();
result.clearText = clearText;
// Extract signature from clear-signed text
PGPObjectFactory pgpFact = new PGPObjectFactory(in);
PGPSignatureList p3 = (PGPSignatureList) pgpFact.nextObject();
PGPSignature sig = p3.get(0);
// Decode public key
PGPPublicKey publicKey = pubKeyRing.getPublicKey(sig.getKeyID());
// Verify signature
Security.addProvider(new BouncyCastleProvider());
sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"),
publicKey);
// RFC 4880, section 7: http://tools.ietf.org/html/rfc4880#section-7
// The signature must be validated using clear text:
// - without trailing white spaces on every line
// - using CR LF line endings, no matter what the original line ending is
// - without the latest line ending
BufferedReader textIn = new BufferedReader(new InputStreamReader(
new ByteArrayInputStream(clearText)));
while (true) {
// remove trailing whitespace and line endings
String line = StringUtils.rtrim(textIn.readLine());
sig.update(line.getBytes());
if (!textIn.ready()) // skip latest line ending
break;
// always use CR LF
sig.update((byte) '\r');
sig.update((byte) '\n');
}
// Prepare the result
result.verified = sig.verify();
} catch (Exception e) {
result.error = e;
} finally {
if (in != null)
try {
in.close();
} catch (IOException e) {
// ignored
}
}
return result;
}
public static void main(String[] args) throws Exception {
VerifyResult verify = verify(new File(
"/home/megabug/git/arduino/test.txt.asc"), new PackagersPublicKeys());
System.out.println(verify.verified);
}
}

View File

@ -1,99 +0,0 @@
/*
* This file is part of Arduino.
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*
* Copyright 2013 Arduino LLC (http://www.arduino.cc/)
*/
package cc.arduino.packages.security.keys;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPUtil;
public class PackagersPublicKeys extends PGPPublicKeyRingCollection {
public static final String ARDUINO_PK = "" //
+ "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
+ "Version: GnuPG v1.4.11 (GNU/Linux)\n"
+ "\n"
+ "mQINBFJ9IskBEAD3vGGYFl+gib5WURZwcW7e1Z2+ZAd48LP+KsZ2RVHv7FhzsH1s\n"
+ "eSRNsuLUXV0DHTCGUUqvQYV/+HLnv4hQvRFogql5zapQldS4mhWO0jcVuee3lDun\n"
+ "nmQEN3Ikn0Zf2+sQD0iMXk8eRz3MJx2xDs7yK3ZHkdkie7pqNKg6yrJ64x5H3HJn\n"
+ "y7aOSN3ClNgTbxdNlfCQfhex12c+fiOqVO4f5KyYvRo3zBMv8TV4JL0KG1L+uuKU\n"
+ "uuXyG4jUhldpf+1fazX3bW0432rfnxNI2JsPCQ5h95nQNrW0LRS1Nrts8UTePt/9\n"
+ "trJ1sIlSMRyG7mkq3gzTf4a2BaUejHHNGLwXBBMyGNQqei+hawwnimlD7egXKpa3\n"
+ "uy8La2rB37RK672CjsN2KSOU7B6UpTQY6VCjkC0yQY6u9Kp8P9XY5M6HIZhBwVpk\n"
+ "kPfJ93b73leMcSDSU6cCcCdWpkCUDQNpBLa4k0vr4nEC5hs8Q6RjpgVgGDulY2Xf\n"
+ "hWkrh430r+a50wbEmSZwPg05wnC0n2pu+hpSF7mNx4FhnfXQ3eaJHvW/4hCdwxAg\n"
+ "tbC+yXPmEJ01h3cK53xI8Usve4pizaxb2FuMf5FmOTt/B/H+KmHAOLcY3xCMxF9t\n"
+ "wcXVHdfkWfZk4LK2RUo+oe3Z2SXSGuOj61pP5wnvRYojtURwjrehArTrpwARAQAB\n"
+ "tCZBcmR1aW5vIFBhY2thZ2VzIDxwYWNrYWdlc0BhcmR1aW5vLmNjPokCPgQTAQIA\n"
+ "KAUCUn0iyQIbAwUJCWYBgAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQPrLD\n"
+ "cgsG1iRL7A/8Cf/S6xgksnSk1GD+6tSLEZHku7tLEhiCX38pS8a6UBAj1UGrbxPn\n"
+ "kS0iPLcfJG7AblI4EjrYTMaLHUL0UtcOvq8+F9/NrZAVW6+xOpm9LTQhUMh+ddCx\n"
+ "6igY3BRr9WtNkrowzMUGpGrJzIw7v3hiJbXDNIpTwoLF4aFEgOJXyJZawp8rjBOw\n"
+ "bnRlq9MTC/7+nm/d7i7nsRxDyGcZllVDIFI38sVVmLL8eBd7z9Vn1RsZDkPzhGzM\n"
+ "aKdFCU7hD15H3hPkeidkbLwmd5jihZCDDd2LhGtMFo3cwqouKo/UTaYomNP2iGlU\n"
+ "2BBpuQTPcJy2d1d8lCr19yARcJCVC9H6sISkXPHO0EMgGrpdFgxDVGeEkvn1scHV\n"
+ "x+k4BCOMl1WfsD4JkAJ5RyyZNjP0oDlY8SROfT479Ypb6qLMGCOujxjHapv/t2PH\n"
+ "2cjadiMP62AN3rIiMTZWpCgL+bu3j8hsbAnlaINxoiab72+8uuA53o2SKWIA4J24\n"
+ "0wu7ETW0QQkxym/ammX/nXgap/R9u/A8kGx+QKPyjptO+hnc7vgGAMEIrVDsKeTp\n"
+ "AmIwtxvK3AIKGkup+E+ee2kzBhJHhsoDpmJZgaIxoiCdOZglaA+V53I16Vv+fiC1\n"
+ "SW9cN5UQvlNycu8QFQwwz/Eg7M8abQDXBgf6znAKt0wSn6tI/b/NBmG5Ag0EUn0i\n"
+ "yQEQAK8ZvoX51FizIt49nfwWR6w7CCG35B92oVTKn1oLPSF9fU75dmBd57sFAle0\n"
+ "Zm5DzfzCQ1d6voo8HhmUQHIE1NamC1YE6c2AKvc4xx4ltjjPqi8+KJ1y5gNz1M5Q\n"
+ "ZRnzjxjkCePSRxQXoEDNINryPvNQLzrFbtm5R2tsygwqaVxhJok4hny1srhxd8IZ\n"
+ "rz5MBlRtRr31D494GRD4iSKyvpAC+zh2ZL1+zUtg7qQU0FybUJ/hIJ2DRHNwuutp\n"
+ "2EzbDwJJNNDjjNC8NKdJ4GgOJJnKGU52OfdmeEeI1+wDm3/FvI4lSS9O/ay4ty3/\n"
+ "wSwhGKOWNXowGFVXdzxYyCOf1NVDHn8Vj8sU2lHw5Fn2RA41xAs33aLPjLmdv7xa\n"
+ "7mJSp0cfiudPyVWP0D+/269kMq6W3V9IFeRQMxObNXWACKzuaaLi60ncGaXvM/q1\n"
+ "2O0HvQ9+BlLE7DSQWGb8NTngSAFYUYdWZ1GhiyTvFKkSDIAhkQfYLc0Kky6y1D2J\n"
+ "w0alVMdroHwf67V+ya2+Ac8EGv0oQvAF7ug1Ymnjx59kqV6IxdsPdRAmfZT63yJS\n"
+ "C6ZDEbuqP3SUCehSwO/GW0Echwuga87At4RJ6OQ8HxdhjFMGjQANp+He6L7O2dav\n"
+ "+JbH1687fc65VO8sTbhfW6Ntzr/MIVdS6rc1RzHMfMeVcuFJABEBAAGJAiUEGAEC\n"
+ "AA8FAlJ9IskCGwwFCQlmAYAACgkQPrLDcgsG1iRQwg//VhFjyz1q/jxB7HbUEGhT\n"
+ "wNsT5lOVXIJy8Y6CyAQLjI5LatZxMdIqZOlkPgHiMpMqJqvDgBgR/44UKL4yzvmv\n"
+ "/6DIeMngej2oD794Q4j4LlnQopolvZy7dSyQqWX3kqEABAPMYnLhR9r/PQPiienR\n"
+ "E7p1+zC/czcpL7wHKChjPgegPDrJ7yOug9IgwFSfokF5BFR3aNJNOxEHd+YSXfS4\n"
+ "i4Eef3YovQfUvMfq7jux7Qsi8igzvm782pPsylPwysd/d0emlkGqMLGHWh+r1eIy\n"
+ "UzOXgfhwgN38RB/p1joVSZGpmTu6y9e50HME9FrYEmCrNwYTOi1fQB/IHr7lg1qT\n"
+ "/Bap938b6vm08pEDnVLSahsgdJdG8YYwJEg2BJnpThIGHnle9Ahmk3OMI7Wl9VsQ\n"
+ "1MJ+va/rWjKvq6z7k0YzQbrJStrlrErbi4DN0YTmNV2M6IDcySjhCSAww7nqHiIx\n"
+ "sJGggMBQS0/KQCsyXHeLpJwoSTv16c9UajV7/wJA8r7yNZV9a/5LrC2hRoN4RnU5\n"
+ "kN//5xNON5L5Qd40XslUaFv4J/f21xuLgCkDb9N/jqwq7gLkkP/1WX8UkmWLvGM0\n"
+ "J5DkabHzgusefEG9pNsFwExzAg4IFYKgG2qbS0zNQV8uMUD9vF7K/6YZgcBjH5gc\n"
+ "KCcKZZVUQLJhOIwgHQMy7ck=\n" //
+ "=u0/X\n" //
+ "-----END PGP PUBLIC KEY BLOCK-----\n";
public PackagersPublicKeys() throws IOException, PGPException {
super(PGPUtil.getDecoderStream(new ByteArrayInputStream(ARDUINO_PK.getBytes())));
}
}

View File

@ -91,19 +91,13 @@ public class ArchiveExtractor {
// Create an ArchiveInputStream with the correct archiving algorithm // Create an ArchiveInputStream with the correct archiving algorithm
if (archiveFile.getName().endsWith("tar.bz2")) { if (archiveFile.getName().endsWith("tar.bz2")) {
InputStream fin = new FileInputStream(archiveFile); in = new TarArchiveInputStream(new BZip2CompressorInputStream(new FileInputStream(archiveFile)));
fin = new BZip2CompressorInputStream(fin);
in = new TarArchiveInputStream(fin);
} else if (archiveFile.getName().endsWith("zip")) { } else if (archiveFile.getName().endsWith("zip")) {
InputStream fin = new FileInputStream(archiveFile); in = new ZipArchiveInputStream(new FileInputStream(archiveFile));
in = new ZipArchiveInputStream(fin);
} else if (archiveFile.getName().endsWith("tar.gz")) { } else if (archiveFile.getName().endsWith("tar.gz")) {
InputStream fin = new FileInputStream(archiveFile); in = new TarArchiveInputStream(new GzipCompressorInputStream(new FileInputStream(archiveFile)));
fin = new GzipCompressorInputStream(fin);
in = new TarArchiveInputStream(fin);
} else if (archiveFile.getName().endsWith("tar")) { } else if (archiveFile.getName().endsWith("tar")) {
InputStream fin = new FileInputStream(archiveFile); in = new TarArchiveInputStream(new FileInputStream(archiveFile));
in = new TarArchiveInputStream(fin);
} else { } else {
throw new IOException("Archive format not supported."); throw new IOException("Archive format not supported.");
} }
@ -276,8 +270,9 @@ public class ArchiveExtractor {
} }
private static void copyStreamToFile(InputStream in, long size, File outputFile) throws IOException { private static void copyStreamToFile(InputStream in, long size, File outputFile) throws IOException {
FileOutputStream fos = new FileOutputStream(outputFile); FileOutputStream fos = null;
try { try {
fos = new FileOutputStream(outputFile);
// if size is not available, copy until EOF... // if size is not available, copy until EOF...
if (size == -1) { if (size == -1) {
byte buffer[] = new byte[4096]; byte buffer[] = new byte[4096];
@ -299,7 +294,9 @@ public class ArchiveExtractor {
size -= length; size -= length;
} }
} finally { } finally {
fos.close(); if (fos != null) {
fos.close();
}
} }
} }

View File

@ -40,19 +40,18 @@ public class FileHash {
* Calculate a message digest of a file using the algorithm specified. The * Calculate a message digest of a file using the algorithm specified. The
* result is a string containing the algorithm name followed by ":" and by the * result is a string containing the algorithm name followed by ":" and by the
* resulting hash in hex. * resulting hash in hex.
* *
* @param file * @param file
* @param algorithm * @param algorithm For example "SHA-256"
* For example "SHA-256"
* @return The algorithm followed by ":" and the hash, for example:<br /> * @return The algorithm followed by ":" and the hash, for example:<br />
* "SHA-256:ee6796513086080cca078cbb383f543c5e508b647a71c9d6f39b7bca41071883" * "SHA-256:ee6796513086080cca078cbb383f543c5e508b647a71c9d6f39b7bca41071883"
* @throws IOException * @throws IOException
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
*/ */
public static String hash(File file, String algorithm) throws IOException, public static String hash(File file, String algorithm) throws IOException, NoSuchAlgorithmException {
NoSuchAlgorithmException { FileInputStream in = null;
FileInputStream in = new FileInputStream(file);
try { try {
in = new FileInputStream(file);
byte buff[] = new byte[10240]; byte buff[] = new byte[10240];
MessageDigest digest = MessageDigest.getInstance(algorithm); MessageDigest digest = MessageDigest.getInstance(algorithm);
while (in.available() > 0) { while (in.available() > 0) {
@ -69,7 +68,9 @@ public class FileHash {
} }
return algorithm + ":" + res; return algorithm + ":" + res;
} finally { } finally {
in.close(); if (in != null) {
in.close();
}
} }
} }
} }

View File

@ -1,5 +1,6 @@
package processing.app; package processing.app;
import cc.arduino.contributions.SignatureVerificationFailedException;
import cc.arduino.contributions.libraries.LibrariesIndexer; import cc.arduino.contributions.libraries.LibrariesIndexer;
import cc.arduino.contributions.packages.ContributedTool; import cc.arduino.contributions.packages.ContributedTool;
import cc.arduino.contributions.packages.ContributionsIndexer; import cc.arduino.contributions.packages.ContributionsIndexer;
@ -232,13 +233,6 @@ public class BaseNoGui {
return librariesFolders; return librariesFolders;
} }
/**
* Return an InputStream for a file inside the Processing lib folder.
*/
static public InputStream getLibStream(String filename) throws IOException {
return new FileInputStream(new File(getContentFile("lib"), filename));
}
static public Platform getPlatform() { static public Platform getPlatform() {
return platform; return platform;
} }
@ -577,7 +571,7 @@ public class BaseNoGui {
static public void initPackages() throws Exception { static public void initPackages() throws Exception {
indexer = new ContributionsIndexer(BaseNoGui.getSettingsFolder()); indexer = new ContributionsIndexer(BaseNoGui.getSettingsFolder());
File indexFile = indexer.getIndexFile(); File indexFile = indexer.getIndexFile("package_index.json");
File defaultPackageJsonFile = new File(getContentFile("dist"), "package_index.json"); File defaultPackageJsonFile = new File(getContentFile("dist"), "package_index.json");
if (!indexFile.isFile() || (defaultPackageJsonFile.isFile() && defaultPackageJsonFile.lastModified() > indexFile.lastModified())) { if (!indexFile.isFile() || (defaultPackageJsonFile.isFile() && defaultPackageJsonFile.lastModified() > indexFile.lastModified())) {
FileUtils.copyFile(defaultPackageJsonFile, indexFile); FileUtils.copyFile(defaultPackageJsonFile, indexFile);
@ -594,7 +588,20 @@ public class BaseNoGui {
} }
} }
} }
indexer.parseIndex();
File indexSignatureFile = indexer.getIndexFile("package_index.json.sig");
File defaultPackageJsonSignatureFile = new File(getContentFile("dist"), "package_index.json.sig");
if (!indexSignatureFile.isFile() || (defaultPackageJsonSignatureFile.isFile() && defaultPackageJsonSignatureFile.lastModified() > indexSignatureFile.lastModified())) {
FileUtils.copyFile(defaultPackageJsonSignatureFile, indexSignatureFile);
}
try {
indexer.parseIndex();
} catch (SignatureVerificationFailedException e) {
indexFile.delete();
indexSignatureFile.delete();
throw e;
}
indexer.syncWithFilesystem(getHardwareFolder()); indexer.syncWithFilesystem(getHardwareFolder());
packages = new HashMap<String, TargetPackage>(); packages = new HashMap<String, TargetPackage>();
@ -610,13 +617,17 @@ public class BaseNoGui {
if (defaultLibraryJsonFile.isFile()) { if (defaultLibraryJsonFile.isFile()) {
FileUtils.copyFile(defaultLibraryJsonFile, librariesIndexFile); FileUtils.copyFile(defaultLibraryJsonFile, librariesIndexFile);
} else { } else {
FileOutputStream out = null;
try { try {
// Otherwise create an empty packages index // Otherwise create an empty packages index
FileOutputStream out = new FileOutputStream(librariesIndexFile); out = new FileOutputStream(librariesIndexFile);
out.write("{ \"libraries\" : [ ] }".getBytes()); out.write("{ \"libraries\" : [ ] }".getBytes());
out.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
} }
} }
} }

View File

@ -45,7 +45,7 @@ public class PreferencesData {
// start by loading the defaults, in case something // start by loading the defaults, in case something
// important was deleted from the user prefs // important was deleted from the user prefs
try { try {
prefs.load(BaseNoGui.getLibStream(PREFS_FILE)); prefs.load(new File(BaseNoGui.getContentFile("lib"), PREFS_FILE));
} catch (IOException e) { } catch (IOException e) {
BaseNoGui.showError(null, _("Could not read default settings.\n" + BaseNoGui.showError(null, _("Could not read default settings.\n" +
"You'll need to reinstall Arduino."), e); "You'll need to reinstall Arduino."), e);
@ -94,41 +94,6 @@ public class PreferencesData {
} }
static public String[] loadStrings(InputStream input) {
try {
BufferedReader reader =
new BufferedReader(new InputStreamReader(input, "UTF-8"));
String lines[] = new String[100];
int lineCount = 0;
String line = null;
while ((line = reader.readLine()) != null) {
if (lineCount == lines.length) {
String temp[] = new String[lineCount << 1];
System.arraycopy(lines, 0, temp, 0, lineCount);
lines = temp;
}
lines[lineCount++] = line;
}
reader.close();
if (lineCount == lines.length) {
return lines;
}
// resize array to appropriate amount for these lines
String output[] = new String[lineCount];
System.arraycopy(lines, 0, output, 0, lineCount);
return output;
} catch (IOException e) {
e.printStackTrace();
//throw new RuntimeException("Error inside loadStrings()");
}
return null;
}
static protected void save() { static protected void save() {
if (!doSave) if (!doSave)
return; return;
@ -139,19 +104,25 @@ public class PreferencesData {
if (preferencesFile == null) return; if (preferencesFile == null) return;
// Fix for 0163 to properly use Unicode when writing preferences.txt // Fix for 0163 to properly use Unicode when writing preferences.txt
PrintWriter writer = PApplet.createWriter(preferencesFile); PrintWriter writer = null;
try {
writer = PApplet.createWriter(preferencesFile);
String[] keys = prefs.keySet().toArray(new String[0]); String[] keys = prefs.keySet().toArray(new String[0]);
Arrays.sort(keys); Arrays.sort(keys);
for (String key: keys) { for (String key : keys) {
if (key.startsWith("runtime.")) if (key.startsWith("runtime."))
continue; continue;
writer.println(key + "=" + prefs.get(key)); writer.println(key + "=" + prefs.get(key));
}
writer.flush();
} finally {
if (writer != null) {
writer.close();
}
} }
writer.flush();
writer.close();
try { try {
BaseNoGui.getPlatform().fixPrefsFilePermissions(preferencesFile); BaseNoGui.getPlatform().fixPrefsFilePermissions(preferencesFile);
} catch (Exception e) { } catch (Exception e) {

View File

@ -1210,12 +1210,12 @@ public class Compiler implements MessageConsumer {
// 2. run preproc on that code using the sugg class name // 2. run preproc on that code using the sugg class name
// to create a single .java file and write to buildpath // to create a single .java file and write to buildpath
FileOutputStream outputStream = null;
try { try {
// Output file // Output file
File streamFile = new File(buildPath, sketch.getName() + ".cpp"); File streamFile = new File(buildPath, sketch.getName() + ".cpp");
FileOutputStream outputStream = new FileOutputStream(streamFile); outputStream = new FileOutputStream(streamFile);
preprocessor.write(outputStream); preprocessor.write(outputStream);
outputStream.close();
} catch (FileNotFoundException fnfe) { } catch (FileNotFoundException fnfe) {
fnfe.printStackTrace(); fnfe.printStackTrace();
String msg = _("Build folder disappeared or could not be written"); String msg = _("Build folder disappeared or could not be written");
@ -1230,6 +1230,14 @@ public class Compiler implements MessageConsumer {
System.err.println(I18n.format(_("Uncaught exception type: {0}"), ex.getClass())); System.err.println(I18n.format(_("Uncaught exception type: {0}"), ex.getClass()));
ex.printStackTrace(); ex.printStackTrace();
throw new RunnerException(ex.toString()); throw new RunnerException(ex.toString());
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
//noop
}
}
} }
// grab the imports from the code just preproc'd // grab the imports from the code just preproc'd

View File

@ -21,18 +21,14 @@
*/ */
package processing.app.helpers; package processing.app.helpers;
import java.io.File; import processing.app.legacy.PApplet;
import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import processing.app.legacy.PApplet;
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class PreferencesMap extends LinkedHashMap<String, String> { public class PreferencesMap extends LinkedHashMap<String, String> {
@ -71,7 +67,15 @@ public class PreferencesMap extends LinkedHashMap<String, String> {
* @throws IOException * @throws IOException
*/ */
public void load(File file) throws IOException { public void load(File file) throws IOException {
load(new FileInputStream(file)); FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
load(fileInputStream);
} finally {
if (fileInputStream != null) {
fileInputStream.close();
}
}
} }
protected String processPlatformSuffix(String key, String suffix, boolean isCurrentPlatform) { protected String processPlatformSuffix(String key, String suffix, boolean isCurrentPlatform) {

View File

@ -266,9 +266,20 @@ public class PApplet {
} }
static public String[] loadStrings(File file) { static public String[] loadStrings(File file) {
InputStream is = createInput(file); InputStream is = null;
if (is != null) return loadStrings(is); try {
return null; is = createInput(file);
if (is != null) return loadStrings(is);
return null;
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// noop
}
}
}
} }
static public String[] loadStrings(InputStream input) { static public String[] loadStrings(InputStream input) {
@ -319,14 +330,29 @@ public class PApplet {
static public void saveStrings(File file, String strings[]) { static public void saveStrings(File file, String strings[]) {
saveStrings(createOutput(file), strings); OutputStream outputStream = null;
try {
outputStream = createOutput(file);
saveStrings(outputStream, strings);
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
//noop
}
}
}
} }
static public void saveStrings(OutputStream output, String strings[]) { static public void saveStrings(OutputStream output, String strings[]) {
PrintWriter writer = createWriter(output); PrintWriter writer = createWriter(output);
for (int i = 0; i < strings.length; i++) { if (writer == null) {
writer.println(strings[i]); return;
}
for (String string : strings) {
writer.println(string);
} }
writer.flush(); writer.flush();
writer.close(); writer.close();

View File

@ -346,6 +346,8 @@
<antcall target="macosx-build-common-avr-toolchain" /> <antcall target="macosx-build-common-avr-toolchain" />
<antcall target="package-library-index-json-bundle"/>
<antcall target="assemble"> <antcall target="assemble">
<param name="target.path" value="${staging_folder}/work/${staging_hardware_folder}/.." /> <param name="target.path" value="${staging_folder}/work/${staging_hardware_folder}/.." />
</antcall> </antcall>
@ -609,7 +611,7 @@
<chmod perm="755" file="linux/work/lib/libastylej.so" /> <chmod perm="755" file="linux/work/lib/libastylej.so" />
</target> </target>
<target name="linux32-build" depends="linux-build" unless="light_bundle" description="Build linux (32-bit) version"> <target name="linux32-build" depends="linux-build" description="Build linux (32-bit) version">
<antcall target="avr-toolchain-bundle"> <antcall target="avr-toolchain-bundle">
<param name="unpack_target" value="untar"/> <param name="unpack_target" value="untar"/>
<param name="gcc_archive_file" value="avr-gcc-4.8.1-arduino5-i686-pc-linux-gnu.tar.bz2"/> <param name="gcc_archive_file" value="avr-gcc-4.8.1-arduino5-i686-pc-linux-gnu.tar.bz2"/>
@ -617,9 +619,11 @@
<param name="avrdude_archive_file" value="avrdude-6.0.1-arduino5-i686-pc-linux-gnu.tar.bz2"/> <param name="avrdude_archive_file" value="avrdude-6.0.1-arduino5-i686-pc-linux-gnu.tar.bz2"/>
<param name="avrdude_version" value="6.0.1-arduino5"/> <param name="avrdude_version" value="6.0.1-arduino5"/>
</antcall> </antcall>
<antcall target="package-library-index-json-bundle"/>
</target> </target>
<target name="linux64-build" depends="linux-build" unless="light_bundle" description="Build linux (64-bit) version"> <target name="linux64-build" depends="linux-build" description="Build linux (64-bit) version">
<antcall target="avr-toolchain-bundle"> <antcall target="avr-toolchain-bundle">
<param name="unpack_target" value="untar"/> <param name="unpack_target" value="untar"/>
<param name="gcc_archive_file" value="avr-gcc-4.8.1-arduino5-x86_64-pc-linux-gnu.tar.bz2"/> <param name="gcc_archive_file" value="avr-gcc-4.8.1-arduino5-x86_64-pc-linux-gnu.tar.bz2"/>
@ -627,6 +631,8 @@
<param name="avrdude_archive_file" value="avrdude-6.0.1-arduino5-x86_64-pc-linux-gnu.tar.bz2"/> <param name="avrdude_archive_file" value="avrdude-6.0.1-arduino5-x86_64-pc-linux-gnu.tar.bz2"/>
<param name="avrdude_version" value="6.0.1-arduino5"/> <param name="avrdude_version" value="6.0.1-arduino5"/>
</antcall> </antcall>
<antcall target="package-library-index-json-bundle"/>
</target> </target>
<target name="linux32-run" depends="linux32-build" description="Run Linux (32-bit) version"> <target name="linux32-run" depends="linux32-build" description="Run Linux (32-bit) version">
@ -846,6 +852,8 @@
<param name="avrdude_archive_file" value="avrdude-6.0.1-arduino5-i686-mingw32.zip"/> <param name="avrdude_archive_file" value="avrdude-6.0.1-arduino5-i686-mingw32.zip"/>
<param name="avrdude_version" value="6.0.1-arduino5"/> <param name="avrdude_version" value="6.0.1-arduino5"/>
</antcall> </antcall>
<antcall target="package-library-index-json-bundle"/>
</target> </target>
<target name="windows-run" depends="windows-build" <target name="windows-run" depends="windows-build"
@ -950,10 +958,20 @@
<echo append="true" file="${staging_folder}/work/${staging_hardware_folder}/tools/avr/builtin_tools_versions.txt" message="arduino.avrdude=${avrdude_version}${line.separator}"/> <echo append="true" file="${staging_folder}/work/${staging_hardware_folder}/tools/avr/builtin_tools_versions.txt" message="arduino.avrdude=${avrdude_version}${line.separator}"/>
<echo append="true" file="${staging_folder}/work/${staging_hardware_folder}/tools/avr/builtin_tools_versions.txt" message="arduino.avr-gcc=${gcc_version}${line.separator}"/> <echo append="true" file="${staging_folder}/work/${staging_hardware_folder}/tools/avr/builtin_tools_versions.txt" message="arduino.avr-gcc=${gcc_version}${line.separator}"/>
</target>
<target name="package-library-index-json-bundle">
<mkdir dir="${staging_folder}/work/${staging_hardware_folder}/../dist/"/> <mkdir dir="${staging_folder}/work/${staging_hardware_folder}/../dist/"/>
<get src="http://downloads.arduino.cc/packages/package_index.json" dest="${staging_folder}/work/${staging_hardware_folder}/../dist/package_index.json" verbose="true" skipexisting="false" />
<get src="http://downloads.arduino.cc/libraries/library_index.json" dest="${staging_folder}/work/${staging_hardware_folder}/../dist/library_index.json" verbose="true" skipexisting="false" /> <get src="http://downloads.arduino.cc/packages/package_index.json.gz" dest="${staging_folder}/work/${staging_hardware_folder}/../dist/" verbose="true" skipexisting="false" />
<gunzip src="${staging_folder}/work/${staging_hardware_folder}/../dist/package_index.json.gz" dest="${staging_folder}/work/${staging_hardware_folder}/../dist/"/>
<delete file="${staging_folder}/work/${staging_hardware_folder}/../dist/package_index.json.gz"/>
<get src="http://downloads.arduino.cc/packages/package_index.json.sig" dest="${staging_folder}/work/${staging_hardware_folder}/../dist/" verbose="true" skipexisting="false" />
<get src="http://downloads.arduino.cc/libraries/library_index.json.gz" dest="${staging_folder}/work/${staging_hardware_folder}/../dist/" verbose="true" skipexisting="false" />
<gunzip src="${staging_folder}/work/${staging_hardware_folder}/../dist/library_index.json.gz" dest="${staging_folder}/work/${staging_hardware_folder}/../dist/"/>
<delete file="${staging_folder}/work/${staging_hardware_folder}/../dist/library_index.json.gz"/>
<delete dir="${staging_folder}/work/${staging_hardware_folder}/tmp"/> <delete dir="${staging_folder}/work/${staging_hardware_folder}/tmp"/>
</target> </target>

View File

@ -97,7 +97,7 @@
<!-- In 0149, removed /System/Library/Java from the CLASSPATH because <!-- In 0149, removed /System/Library/Java from the CLASSPATH because
it can cause problems if users have installed weird files there. it can cause problems if users have installed weird files there.
http://dev.processing.org/bugs/show_bug.cgi?id=1045 --> http://dev.processing.org/bugs/show_bug.cgi?id=1045 -->
<string>$JAVAROOT/antlr.jar:$JAVAROOT/apple.jar:$JAVAROOT/arduino-core.jar:$JAVAROOT/bcpg-jdk15on-149.jar:$JAVAROOT/bcprov-jdk15on-149.jar:$JAVAROOT/commons-codec-1.7.jar:$JAVAROOT/commons-compress-1.8.jar:$JAVAROOT/commons-exec-1.1.jar:$JAVAROOT/commons-httpclient-3.1.jar:$JAVAROOT/commons-lang3-3.3.2.jar:$JAVAROOT/commons-logging-1.0.4.jar:$JAVAROOT/ecj.jar:$JAVAROOT/guava-18.0.jar:$JAVAROOT/jackson-annotations-2.2.3.jar:$JAVAROOT/jackson-core-2.2.3.jar:$JAVAROOT/jackson-databind-2.2.3.jar:$JAVAROOT/jackson-module-mrbean-2.2.3.jar:$JAVAROOT/java-semver-0.8.0.jar:$JAVAROOT/jmdns-3.4.1.jar:$JAVAROOT/jna.jar:$JAVAROOT/jsch-0.1.50.jar:$JAVAROOT/jssc-2.8.0.jar:$JAVAROOT/pde.jar:$JAVAROOT/quaqua.jar</string> <string>$JAVAROOT/antlr.jar:$JAVAROOT/apple.jar:$JAVAROOT/arduino-core.jar:$JAVAROOT/bcpg-jdk15on-152.jar:$JAVAROOT/bcprov-jdk15on-152.jar:$JAVAROOT/commons-codec-1.7.jar:$JAVAROOT/commons-compress-1.8.jar:$JAVAROOT/commons-exec-1.1.jar:$JAVAROOT/commons-httpclient-3.1.jar:$JAVAROOT/commons-lang3-3.3.2.jar:$JAVAROOT/commons-logging-1.0.4.jar:$JAVAROOT/ecj.jar:$JAVAROOT/guava-18.0.jar:$JAVAROOT/jackson-annotations-2.2.3.jar:$JAVAROOT/jackson-core-2.2.3.jar:$JAVAROOT/jackson-databind-2.2.3.jar:$JAVAROOT/jackson-module-mrbean-2.2.3.jar:$JAVAROOT/java-semver-0.8.0.jar:$JAVAROOT/jmdns-3.4.1.jar:$JAVAROOT/jna.jar:$JAVAROOT/jsch-0.1.50.jar:$JAVAROOT/jssc-2.8.0.jar:$JAVAROOT/pde.jar:$JAVAROOT/quaqua.jar</string>
<key>JVMArchs</key> <key>JVMArchs</key>
<array> <array>

Binary file not shown.

View File

@ -18,8 +18,8 @@
<cp>lib/antlr.jar</cp> <cp>lib/antlr.jar</cp>
<cp>lib/apple.jar</cp> <cp>lib/apple.jar</cp>
<cp>lib/arduino-core.jar</cp> <cp>lib/arduino-core.jar</cp>
<cp>lib/bcpg-jdk15on-149.jar</cp> <cp>lib/bcpg-jdk15on-152.jar</cp>
<cp>lib/bcprov-jdk15on-149.jar</cp> <cp>lib/bcprov-jdk15on-152.jar</cp>
<cp>lib/commons-codec-1.7.jar</cp> <cp>lib/commons-codec-1.7.jar</cp>
<cp>lib/commons-compress-1.8.jar</cp> <cp>lib/commons-compress-1.8.jar</cp>
<cp>lib/commons-exec-1.1.jar</cp> <cp>lib/commons-exec-1.1.jar</cp>

View File

@ -18,8 +18,8 @@
<cp>lib/antlr.jar</cp> <cp>lib/antlr.jar</cp>
<cp>lib/apple.jar</cp> <cp>lib/apple.jar</cp>
<cp>lib/arduino-core.jar</cp> <cp>lib/arduino-core.jar</cp>
<cp>lib/bcpg-jdk15on-149.jar</cp> <cp>lib/bcpg-jdk15on-152.jar</cp>
<cp>lib/bcprov-jdk15on-149.jar</cp> <cp>lib/bcprov-jdk15on-152.jar</cp>
<cp>lib/commons-codec-1.7.jar</cp> <cp>lib/commons-codec-1.7.jar</cp>
<cp>lib/commons-compress-1.8.jar</cp> <cp>lib/commons-compress-1.8.jar</cp>
<cp>lib/commons-exec-1.1.jar</cp> <cp>lib/commons-exec-1.1.jar</cp>