boolean uploadPicture(Picture p) {
			try {
				//transferListener.currentFile = p.toString();

				status(su, StatusUpdate.LEVEL_UPLOAD_ONE, GRI18n.getString(MODULE, "upPrep"));

				MultipartEntity entity = new MultipartEntity();

				Charset utf8 = Charset.forName("UTF-8");
				JSONObject jsonEntity = new JSONObject();
				jsonEntity.put("type", "photo");
				if (p.getName() != null)
					jsonEntity.put("name", p.getName());
				if (p.getTitle() != null)
					jsonEntity.put("title", p.getTitle());
				if (p.getDescription() != null)
					jsonEntity.put("description", p.getDescription());
				entity.addPart("entity", new StringBody(jsonEntity.toJSONString(), utf8));

				ContentBody body = new FileBody(p.getUploadSource());
				entity.addPart("file", body);

				BufferedReader entityReader = sendRequest(p.getParentAlbum().getUrl(), "post", entity);

				String url = ((JSONObject) JSONValue.parse(entityReader)).get("url").toString();
				status(su, StatusUpdate.LEVEL_UPLOAD_ONE, GRI18n.getString(MODULE, "upSucc"));
				p.setUrl(url);

				Log.log(Log.LEVEL_INFO, "Uploaded " + p.getUploadSource().toString() + " to " + url);

				return true;
				// set auto-rotate only if we do the rotation in GR, otherwise we'd be overriding the server setting
//				if (p.getAngle() != 0) {
//					opts[5] = new NVPair("auto_rotate", "no");
//				}

				// set up extra fields
//				if (p.getExtraFieldsMap() != null && p.getExtraFieldsMap().size() > 0) {
//					ArrayList optsList = new ArrayList(Arrays.asList(opts));
//
//					Iterator it = p.getExtraFieldsMap().keySet().iterator();
//					while (it.hasNext()) {
//						String name = (String) it.next();
//						String value = p.getExtraField(name);
//
//							optsList.add(new NVPair("extrafield." + name, value, utf8?"UTF-8":null));
//						}
//					}
//
//					opts = (NVPair[]) optsList.toArray(opts);
//				}

				// load and validate the response
//				Properties props = requestResponse(hdrs, data, g.getGalleryUrl(scriptName), true, su, this, transferListener);
//				if (props.getProperty("status").equals(GR_STAT_SUCCESS)) {
//					status(su, StatusUpdate.LEVEL_UPLOAD_ONE, GRI18n.getString(MODULE, "upSucc"));
//					String newItemName = props.getProperty("item_name");
//					if (newItemName != null) {
//						su.doneUploading(newItemName, picture);
//					}
//					return true;
//				} else {
//					Object[] params = {props.getProperty("status_text")};
//					error(su, GRI18n.getString(MODULE, "upErr", params));
//					return false;
//				}
			} catch (GR2Exception gr2e) {
				Log.logException(Log.LEVEL_ERROR, MODULE, gr2e);
				Object[] params = {gr2e.getMessage()};
				error(su, p.toString() + ": " + GRI18n.getString(MODULE, "error", params));
			} catch (IOException ioe) {
				Log.logException(Log.LEVEL_ERROR, MODULE, ioe);
				Object[] params = {ioe.toString()};
				error(su, p.toString() + ": " + GRI18n.getString(MODULE, "error", params));
			}

			return false;
		}
		void runTask() {
			ArrayList<Picture> pictures = g.getAllUploadablePictures();

			// get total file size
			long totalSize = 0;
			Iterator<Picture> iter = pictures.iterator();
			while (iter.hasNext()) {
				Picture p = iter.next();
				totalSize += p.getFileSize();
			}

//			transferListener = new MyTransferListener(su);
//			transferListener.sizeAllFiles = totalSize;
//			transferListener.numberAllFiles = pictures.size();

			su.startProgress(StatusUpdate.LEVEL_UPLOAD_ALL, 0, 100, GRI18n.getString(MODULE, "upPic"), false);

			if (su instanceof UploadProgress) {
				((UploadProgress) su).setCancelListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						su.updateProgressStatus(StatusUpdate.LEVEL_UPLOAD_ALL, GRI18n.getString(MODULE, "upStop"));
						su.setUndetermined(StatusUpdate.LEVEL_UPLOAD_ALL, true);
						interrupt();
						long startTime = System.currentTimeMillis();

						while (!terminated && System.currentTimeMillis() < startTime + 10000) {
							try {
								Thread.sleep(1000);
							} catch (InterruptedException e1) {
							}
						}

						if (!terminated) {
							Log.log(Log.LEVEL_ERROR, "Thread would not terminate properly: killing it");
							thread.stop();

							// since we killed the thread, it's not going to clean up after itself
							cleanUp();
						}

						((UploadProgress) su).done();
					}
				});
			}

			// upload each file, one at a time
			boolean allGood = true;
			//int uploadedCount = 0;
			iter = pictures.iterator();
			while (iter.hasNext() /*&& allGood*/ && !interrupt) {
				Picture p = iter.next();

				/*Object[] params = {
						p.toString(),
						new Integer((uploadedCount + 1)),
						new Integer(pictures.size()),
						new Integer((int) ((transferListener.sizeFilesDone + transferListener.sizeThisFile) / 1024 / 1024)),
						new Integer((int) (transferListener.sizeAllFiles / 1024 / 1024)),
						transferListener.getProjectedTimeLeft()
				};
				su.updateProgressStatus(StatusUpdate.LEVEL_UPLOAD_ALL, GRI18n.getString(MODULE, "upStatus", params));*/

				allGood = uploadPicture(p);

				//su.updateProgressValue(StatusUpdate.LEVEL_UPLOAD_ALL, ++uploadedCount);

				if (allGood) {
					p.getParentAlbum().removePicture(p);
				}
			}

			if (allGood) {
				su.stopProgress(StatusUpdate.LEVEL_UPLOAD_ALL, GRI18n.getString(MODULE, "upComplete"));

				if (su instanceof UploadProgress) {
					if (((UploadProgress) su).isShutdown()) {
						GalleryRemote._().getCore().shutdown(true);
					}
				}

				g.setDirty(false);

				GalleryRemote._().getCore().flushMemory();
			} else {
				su.stopProgress(StatusUpdate.LEVEL_UPLOAD_ALL, GRI18n.getString(MODULE, "upFailed"));
			}
		}