Limiting the size of upload and the file type for umbraco media picket - umbraco

Trying to select media via dialogService like this
dialogService.mediaPicker({
startNodeId: undefined,
multiPicker: false,
cropSize: undefined,
showDetails: true,
callback: function (data) {
}
Is there some way to customise this media picker config and only allow certain media types and specify size as well

I think your best option would be to create an event handler for the Saving event of the MediaService and check for your conditions before the file is saved.
More info here: https://our.umbraco.com/Documentation/Getting-Started/Code/Subscribing-To-Events/
public class RestrictMediaTypeAndSize : ApplicationEventHandler
{
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
MediaService.Saving += MediaService_Saving;
}
private void MediaService_Saving(IMediaService sender, Umbraco.Core.Events.SaveEventArgs<Umbraco.Core.Models.IMedia> e)
{
foreach (var media in e.SavedEntities)
{
//you can check for other types of content
if (media.ContentType.Alias == Image.ModelTypeAlias)
{
var fileExtension = GetFileExtension(media);
if (!HasAllowedExtension(fileExtension))
{
//we cancel the saving process
e.Cancel = true;
//we send a message to the user.
var errorMessage = new EventMessage("Error", $"Files of type {fileExtension} are not allowed.");
e.Messages.Add(errorMessage);
//we found an error so we exit the foreach loop to finish the execution.
break;
}
if (!HasValidDimensions(media))
{
//we cancel the saving process
e.Cancel = true;
//we send a message to the user.
var errorMessage = new EventMessage("Error", "Files with a size of (whatever your restrictions) are not allowed.");
e.Messages.Add(errorMessage);
//we found an error so we exit the foreach loop to finish the execution.
break;
}
}
}
}
private bool HasAllowedExtension(string fileExtension)
{
string[] allowedExtensions = new string[] { ".jpg", ".png" };
return allowedExtensions.Contains(fileExtension);
}
private bool HasValidDimensions(IMedia media)
{
//take the image dimensions for the properties populated when you upload the file.
var height = (int)media.Properties["umbracoHeight"].Value;
var width = (int)media.Properties["umbracoWidth"].Value;
//check for whatever conditions you want.
return height < 1000 && width < 2000;
}
private string GetFileExtension(IMedia media)
{
//The umbracoFile Propery is a Json object and we need the src property from it which is the file path.
var filePath = JObject.Parse(media.Properties["umbracoFile"].Value.ToString()).SelectToken("$.src").Value<string>();
return System.IO.Path.GetExtension(filePath);
}
}

Related

How to delete row in ReCyclerListView On Click of Menu button in Contextual Action Bar In Xamarin Android?

I have followed below link on how to implement Contextual action bar with Recycler View https://stackoverflow.com/a/45911314/6117355...Can any one tell me how to perform some action like (edit/delete) operations on rows of Recyclerview on based of button actions of Contextual action bar in xamarin Android?
Can any one tell me how to perform some action like (edit/delete) operations on rows of Recyclerview on based of button actions of Contextual action bar in xamarin Android?
Firstly, you need to modify PhotoAlbum.cs's Photo[] to a List<Photo> to let it support delete/update operation:
public class PhotoAlbum
{
// Built-in photo collection - this could be replaced with
// a photo database:
...
// Array of photos that make up the album:
private List<Photo> mPhotos;
// Random number generator for shuffling the photos:
Random mRandom;
// Create an instance copy of the built-in photo list and
// create the random number generator:
public PhotoAlbum ()
{
mPhotos =new List<Photo>( mBuiltInPhotos);
mRandom = new Random();
}
// Return the number of photos in the photo album:
public int NumPhotos
{
get { return mPhotos.Count; }
}
// Indexer (read only) for accessing a photo:
public Photo this[int i]
{
get { return mPhotos[i]; }
}
// Add this Method to support update operation
public void UpdateAt(int position, Photo photo)
{
if (photo != null)
mPhotos[position] = photo;
}
public Photo GetAt(int position)
{
return mPhotos[position];
}
// Add this Method to support delete operation
public void RemoveAt(int position)
{
mPhotos.RemoveAt(position);
}
// Pick a random photo and swap it with the top:
public int RandomSwap()
{
// Save the photo at the top:
Photo tmpPhoto = mPhotos[0];
// Generate a next random index between 1 and
// Length (noninclusive):
int rnd = mRandom.Next(1, mPhotos.Count);
// Exchange top photo with randomly-chosen photo:
mPhotos[0] = mPhotos[rnd];
mPhotos[rnd] = tmpPhoto;
// Return the index of which photo was swapped with the top:
return rnd;
}
// Shuffle the order of the photos:
public void Shuffle ()
{
// Use the Fisher-Yates shuffle algorithm:
for (int idx = 0; idx < mPhotos.Count; ++idx)
{
// Save the photo at idx:
Photo tmpPhoto = mPhotos[idx];
// Generate a next random index between idx (inclusive) and
// Length (noninclusive):
int rnd = mRandom.Next(idx, mPhotos.Count);
// Exchange photo at idx with randomly-chosen (later) photo:
mPhotos[idx] = mPhotos[rnd];
mPhotos[rnd] = tmpPhoto;
}
}
}
Then, modify the longClick Event to accept an position param:
public class PhotoViewHolder : RecyclerView.ViewHolder
{
public ImageView Image { get; private set; }
public TextView Caption { get; private set; }
// Get references to the views defined in the CardView layout.
public PhotoViewHolder (View itemView, Action<int> listener,Action<object,View.LongClickEventArgs,int> longClickListener)
: base (itemView)
{
// Locate and cache view references:
Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
Caption = itemView.FindViewById<TextView> (Resource.Id.textView);
// Detect user clicks on the item view and report which item
// was clicked (by position) to the listener:
itemView.Click += (sender, e) => listener (base.Position);
ItemView.LongClick +=(sender,e)=> longClickListener(sender,e,base.Position);
}
}
Then start action mode with position param and inside OnActionItemClicked call the Remove function added to the Adapter:
void OnLongClick(object sender, View.LongClickEventArgs args,int position)
{
mActionMode = new MyActionMode(mActivity,this,position);
mode=mActivity.StartActionMode(mActionMode);
((View)sender).Selected = true;
return;
}
...
public class MyActionMode : Java.Lang.Object, ActionMode.ICallback
{
private Context mContext;
private PhotoAlbumAdapter mAdapter;
private int currentPosition;
public MyActionMode(Context context):this(context,null,0)
{
}
public MyActionMode(Context context, PhotoAlbumAdapter adapter,int position)
{
mContext = context;
mAdapter = adapter;
currentPosition = position;
}
public bool OnActionItemClicked(ActionMode mode, IMenuItem item)
{
switch (item.ItemId)
{
case Resource.Id.itemOneId:
// do Delete
mAdapter.RemoveAt(currentPosition);
mAdapter.FinishActionMode();
return true;
case Resource.Id.itemTwoId:
// do Update
return true;
default:
return false;
}
}
public bool OnCreateActionMode(ActionMode mode, IMenu menu)
{
mode.MenuInflater.Inflate(Resource.Menu.ContextualMenu, menu);
return true;
}
public void OnDestroyActionMode(ActionMode mode)
{
mode.Dispose();
}
public bool OnPrepareActionMode(ActionMode mode, IMenu menu)
{
return false;
}
}
I've committed the codes to demo project.
Notes: It is the same logic that can apply to the update operation.

Add STOMP header without recreating Message on ChannelInterceptorAdapter

I need to add header to a STOMP message currently it is working as below but i am recreating the message , is it possible to just add native header without having to recreate the message for performance .
public class MyChannelInterceptor extends ChannelInterceptorAdapter {
#Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
StompCommand command = accessor.getCommand();
if(command != null) {
log.debug("Receiving msg {} from {}",command,accessor.getUser().getName());
if(command == StompCommand.SEND) {
log.debug("Adding expires header to msg {} from {}",command,accessor.getUser().getName());
String ttlString = accessor.getFirstNativeHeader("ttl");
long ttl = 30000;
try {
ttl = Long.parseLong(ttlString);
}
catch(Exception ex) {
log.error("TTL header received but not in correct format {}",ttlString);
}
accessor.addNativeHeader("expires", Long.toString(System.currentTimeMillis() + ttl));
return MessageBuilder.createMessage(message.getPayload(), accessor.getMessageHeaders());
}
}
return message;
}
}
This is what i was looking for
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
The above code will get the actual StompHeaderAccessor of the message so if you manipulate the native headers they are directly reflected on the message while
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
will get a clone of the headers and you have to create a new message with the new cloned headers
full fixed code below
#Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
// StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
if(accessor != null) {
StompCommand command = accessor.getCommand();
if(command != null) {
log.debug("Receiving msg {} from {}",command,accessor.getUser().getName());
if(command == StompCommand.SEND) {
log.debug("Adding expires header to msg {} from {}",command,accessor.getUser().getName());
String ttlString = accessor.getFirstNativeHeader("ttl");
long ttl = 30000;
if(ttlString != null) {
try {
ttl = Long.parseLong(ttlString);
}
catch(Exception ex) {
log.error("TTL header received but not in correct format {}",ttlString);
}
}
accessor.addNativeHeader("expires", Long.toString(System.currentTimeMillis() + ttl));
// I don't need any more to create a new message
//return MessageBuilder.createMessage(message.getPayload(), accessor.getMessageHeaders());
}
}
}
return message;
}
Since addNativeHeader succeeds, that indicates the message is still mutable - see addNativeHeader().
In any case, since the NATIVE_HEADERS message header is a MultiValueMap-valued header, you can update the header contents in-place.
Hence, there is no need to create a new message.
You would have to create a new message if you add a new header to the message itself (rather than updating the mutable contents of an existing header).
EDIT
I just ran a test; as long as the message is still mutable, you can change it...
#Test
public void test() {
Map<String, Object> map = new HashMap<String, Object>();
MutableMessageHeaders headers = new MutableMessageHeaders(map);
Message<String> message = MessageBuilder.createMessage("foo", headers);
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
accessor.addNativeHeader("foo", "bar");
System.out.println(message.getHeaders().get(NativeMessageHeaderAccessor.NATIVE_HEADERS));
accessor.setImmutable();
try {
accessor.addNativeHeader("baz", "qux");
fail("expected IllegalStateException");
}
catch (IllegalStateException e) {
}
}
That said, are you experiencing a performance problem or is this just a perceived issue. Message creation is not expensive.

navigating a image from page to other in mono android

I have an ImageView and Button in an Activity, lets call it A. When clicking on the Button, I start the image gallery, where I select an image and load that into the ImageView.
On the ImageView I subscribe to the Touch events, where I want to launch another Activity, B.
My question is, how can I in Activity B get the image, which was selected in Activity A? How is data passed fomr Activity to another Activity?
Here is my code in Activity A:
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
_imageView = FindViewById<ImageView>(Resource.Id.imageView1);
_imageView.Touch += TouchMeImageViewOnTouch;
Button button = FindViewById<Button>(Resource.Id.button1);
button.Click += ButtonOnClick;
}
private void ButtonOnClick(object sender, EventArgs eventArgs)
{
Intent = new Intent();
Intent.SetType("image/*");
Intent.SetAction(Intent.ActionGetContent);
StartActivityForResult(Intent.CreateChooser(Intent, "Select Picture"), PickImageId);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if ((requestCode == PickImageId) && (resultCode == Result.Ok) && (data != null))
{
Uri uri = data.Data;
_imageView.SetImageURI(uri);
string path = GetPathToImage(uri);
Toast.MakeText(this, path, ToastLength.Long);
}
}
private string GetPathToImage(Uri uri)
{
string path = null;
string[] projection = new[] { Android.Provider.MediaStore.Images.Media.InterfaceConsts.Data };
using (var cursor = ManagedQuery(uri, projection, null, null, null))
{
if (cursor != null)
{
int columnIndex = cursor.GetColumnIndexOrThrow(
Android.Provider.MediaStore.Images.Media.InterfaceConsts.Data);
cursor.MoveToFirst();
path = cursor.GetString(columnIndex);
}
}
return path;
}
private void TouchMeImageViewOnTouch(object sender, View.TouchEventArgs touchEventArgs)
{
}
In your TouchMeImageViewOnTouch method, you will need to start Activity B. This is done by creating an Intent. This Intent can hold extra stuff the Activity you launch (B), will be able to get hold of.
So I see that you already found out how to get the path to the image, which you simply can pass along to Activity B in the Intent which is done like this:
private void TouchMeImageViewOnTouch(object sender, View.TouchEventArgs touchEventArgs)
{
var intent = new Intent(this, typeof (MainActivity));
intent.PutExtra("imagePath", path);
StartActivity(intent);
}
Then in Activity B you can get the path with:
Intent.GetStringExtra("imagePath");
Then do whatever you want with it.

Partial Unmarshalling of an XML using JAXB to skip some xmlElement

I want to unmarshal an XML file to java object using JAXB. The XML file is very large and contains some nodes which I want to skip in some cases to improve performance as these elements are non editable by client java program.
A sample XML is as follows:
<Example id="10" date="1970-01-01" version="1.0">
<Properties>...</Properties>
<Summary>...</Summary>
<RawData>
<Document id="1">...</Document>
<Document id="2">...</Document>
<Document id="3">...</Document>
------
------
</RawData>
<Location></Location>
<Title></Title>
----- // more elements
</Example>
I have two use cases:
unmarshal into Example object which contains Properties, Summaries, RawData etc. without skipping any RawData. (already done this part)
unmarshal into Example object which exclude RawData. Elements nested in RawData is very large so do not want to read this in this use case.
Now I want to unmarshal the XML such that RawData can be skipped. I have tried the technique provided at this link.
Using technique provided in above link also skips all elements which come after RawData.
I have fixed the issue with XMLEventReader with following code:
public class PartialXmlEventReader implements XMLEventReader {
private final XMLEventReader reader;
private final QName qName;
private boolean skip = false;
public PartialXmlEventReader(final XMLEventReader reader, final QName element) {
this.reader = reader;
this.qName = element;
}
#Override
public String getElementText() throws XMLStreamException {
return reader.getElementText();
}
#Override
public Object getProperty(final String name) throws IllegalArgumentException {
return reader.getProperty(name);
}
#Override
public boolean hasNext() {
return reader.hasNext();
}
#Override
public XMLEvent nextEvent() throws XMLStreamException {
while (isEof(reader.peek())) {
reader.nextEvent();
}
return reader.nextEvent();
}
#Override
public XMLEvent nextTag() throws XMLStreamException {
return reader.nextTag();
}
#Override
public XMLEvent peek() throws XMLStreamException {
return reader.peek();
}
#Override
public Object next() {
return reader.next();
}
#Override
public void remove() {
reader.remove();
}
#Override
public void close() throws XMLStreamException {
reader.close();
}
private boolean isEof(final XMLEvent e) {
boolean returnValue = skip;
switch (e.getEventType()) {
case XMLStreamConstants.START_ELEMENT:
final StartElement se = (StartElement) e;
if (se.getName().equals(qName)) {
skip = true;
returnValue = true;
}
break;
case XMLStreamConstants.END_ELEMENT:
final EndElement ee = (EndElement) e;
if (ee.getName().equals(qName)) {
skip = false;
}
break;
}
return returnValue;
}
}
While Unmarshalling just pass this eventReader to the unmarshal method
final JAXBContext context = JAXBContext.newInstance(classes);
final Unmarshaller um = context.createUnmarshaller();
Reader reader = null;
try {
reader = new BufferedReader(new FileReader(xmlFile));
final QName qName = new QName("RawData");
final XMLInputFactory xif = XMLInputFactory.newInstance();
final XMLEventReader xmlEventReader = xif.createXMLEventReader(reader);
final Example example =
(Example) um.unmarshal(new PartialXmlEventReader(xmlEventReader, qName));
}
} finally {
IOUtils.closeQuietly(reader);
}
I hope this would help
try {
// First create a new XMLInputFactory
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
// Setup a new eventReader
InputStream in = new FileInputStream("myXml");
XMLEventReader eventReader = inputFactory.createXMLEventReader(in);
// Read the XML document
Example example = null;
while (eventReader.hasNext()) {
XMLEvent event = eventReader.nextEvent();
if (event.isStartElement()) {
StartElement startElement = event.asStartElement();
// If we have a example element we create a new example
if (startElement.getName().getLocalPart().equals("Example")) {
example = new Example();
// We read the attributes from this tag and add the date
// and id attribute to our object
Iterator<Attribute> attributes = startElement
.getAttributes();
while (attributes.hasNext()) {
Attribute attribute = attributes.next();
if (attribute.getName().toString().equals("date")) {
example.setDate(attribute.getValue());
} else if (attribute.getName().toString().equals("id")) {
example.setId(attribute.getValue());
}
}
}
//get the Properties tag and add to object example
if (event.isStartElement()) {
if (event.asStartElement().getName().getLocalPart()
.equals("Properties")) {
event = eventReader.nextEvent();
example.setProperites(event.asCharacters().getData());
continue;
}
}
//get the Summary tag and add to object example
if (event.asStartElement().getName().getLocalPart()
.equals("Summary")) {
event = eventReader.nextEvent();
example.setSummary(event.asCharacters().getData());
continue;
}
// when you encounter the Rawdata tag just continue
//without adding it to the object created
if (event.asStartElement().getName().getLocalPart()
.equals("Rawdata")) {
event = eventReader.nextEvent();
// don't do anything
continue;
}
//get the location tag and add to object example
if (event.asStartElement().getName().getLocalPart()
.equals("Location")) {
event = eventReader.nextEvent();
example.setLocation(event.asCharacters().getData());
continue;
}
// read and add other elements that can be added
}
// If we reach the end of an example element/tag i.e closing tag
if (event.isEndElement()) {
EndElement endElement = event.asEndElement();
if (endElement.getName().getLocalPart().equals("Example")) {
//do something
}
}
}
} catch (FileNotFoundException | XMLStreamException e) {
}

Blackberry - Clickable BitmapField With Different ID's

i'm creating one application in which i get gift images with id's from web server through JSON. When i click on any gift image, it goes on next page where it shows all information of that image (get image information with its id from web server through JSON).
Problem is: When i click on any gift image on page to see its relevant information, it gets the last gift image id every time, i want when i click on any image, it gets the specific image id which i click. How it is possible??
Screenshot of the page is : http://ugo.offroadstudios.com/gifts.png
Here is sample code:
public class Gifts extends MainScreen {
String giftsid;
BitmapField giftimg;
public Gifts(){
setTitle("Gift Store");
creategifts();
}
public void creategifts()
{
//Link URL
String strURL = "http://ugo.offroadstudios.com/api/frndgift/?loginusername=adil;deviceside=true";
webConnection wb = new webConnection();
String res = wb.getJson(strURL);
try {
JSONObject object = new JSONObject(res);
if(object.getString("status") == "error")
{
Dialog.alert("Invalid "+object.getString("status"));
}
else
{
int totalgifts;
totalgifts = object.getInt("totalgifts");
Bitmap listThumb;
JSONArray imagearr;
JSONArray giftsidarr;
String imgname;
Bitmap bmpResized;
for(int i=0; i < totalgifts; i++){
imagearr = object.getJSONArray("gifts_image");
imgname = imagearr.getString(i);
giftsidarr = object.getJSONArray("gifts_id");
giftsid = giftsidarr.getString(i);
listThumb = getImage.getImageFromUrl("http://ugo.offroadstudios.com/wp-content/plugins/bp-gifts-rebirth/includes/images/"+imgname+";deviceside=true");
bmpResized = GPATools.ResizeTransparentBitmap(listThumb, 80, 80,
Bitmap.FILTER_LANCZOS, Bitmap.SCALE_TO_FIT);
giftimg =new BitmapField(bmpResized,FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
Dialog.alert("giftsid "+giftsid);
UiApplication.getUiApplication().pushScreen(new SendGift(giftsid));
return true;
}
};
add(giftimg);
}
}
}
catch (JSONException e) {
System.out.println("EX is "+e);
e.printStackTrace();
}
}
}
You are always getting the gift id of the last gift in the list because you have created your buttons with this code:
giftimg =new BitmapField(bmpResized,FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
Dialog.alert("giftsid "+giftsid);
UiApplication.getUiApplication().pushScreen(new SendGift(giftsid));
return true;
}
};
Your navigationClick() method used the giftsid variable, which is a persistent member variable of your class. You assign this variable in your for loop, so the final value it keeps is the last value assigned in the loop (giftsidarr.getString(totalgifts)).
Although you declare the navigationClick() method in a loop where the giftsid is many different values, the navigationClick() method uses the value of giftsid when it is run. The last value.
There's many ways to fix it. You can use a separate constant value in your loop:
final String nextGiftsId = giftsid;
giftimg =new BitmapField(bmpResized,FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
Dialog.alert("nextGiftsId= "+nextGiftsId);
UiApplication.getUiApplication().pushScreen(new SendGift(nextGiftsId));
return true;
}
};
Or, as Signare suggested, attach a cookie to each button that identifies its corresponding gift:
giftimg =new BitmapField(bmpResized,FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
String giftId = (String)getCookie(); // read gift id from the cookie
Dialog.alert("giftId= "+giftId);
UiApplication.getUiApplication().pushScreen(new SendGift(giftId));
return true;
}
};
giftimg.setCookie(giftsid); // set the cookie after creating the field
Inside your for loop, add the following code -
giftimg[i].setChangeListener(this);
Then -
public void fieldChanged(Field field, int context) {
for(int i=0;i<totalgifts;i++) {
if(field == giftimg[i]) {
// you can trigger your event
}
}
EDIT :-
giftimg[i].setChangeListener(listener);
listener = new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
if ( field instanceof BitmapField ) {
for(int i=0;i<totalgifts;i++) {
if ( field == giftimg[i] ) {
// you can trigger your event
}
}
}
}
};

Resources