Apache Cordova
  1. Apache Cordova
  2. CB-362

[ios] target="_blank" links should open in browser (ignoring externalhosts)

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Later
    • Affects Version/s: 1.5.0
    • Fix Version/s: None
    • Component/s: iOS

      Description

      A link such as this:

      <a href="http://google.com" target="_blank">Google</a>

      should open by default in the device's web browser, without being explicitly allowed in the plist (externalhosts).

      This is the current (and, imo, expected) behaviour on Android.

        Issue Links

          Activity

          Hide
          Shazron Abdullah added a comment -

          affects and fix versions were reversed

          Show
          Shazron Abdullah added a comment - affects and fix versions were reversed
          Hide
          Shazron Abdullah added a comment -

          There are two types of anchor tag requests:

          1. Has no target attribute
          2. Has a target attribute that should launch a new Mobile Safari window

          For request type (1), the UIWebViewDelegate gets one NSURLRequest with navigationType UIWebViewNavigationTypeLinkClicked

          For request type (2), the UIWebViewDelegate gets two NSURLRequests with the first being navigationType UIWebViewNavigationTypeLinkClicked, then the second with navigationType UIWebViewNavigationTypeOther

          It is this two request process that prevents this issue from being an easy fix - since at the first request, the NSURLRequest can be rejected before we can process it for the second request (which differentiates it at being target="_blank"), where it can be accepted.

          How do I differentiate between the two types of anchor tags then, to fix this issue? You can't, not easily. This would require saving state (the request) when a UIWebViewNavigationTypeLinkClicked navigationType is encountered, waiting for a set interval then seeing if a request with navigationType UIWebViewNavigationTypeOther follows suit. If it doesn't, process the NSURLRequest normally. If it does, punt it to Mobile Safari. This can potentially be error prone.

          I think what needs to happen is a change in the behaviour for handling anchor tags.

          Here's what I propose:

          If it's an anchor tag with NO target attribute - it can ONLY load file urls, no http urls. Thus only local files can be loaded in the UIWebView in this situation.

          If it's an anchor tag WITH a target attribute - it can ONLY load external http urls, no file urls (besides Mobile Safari won't display any file urls). Thus only external files can be loaded in Mobile Safari in this situation.

          With this new policy, all requests with navigationTypes of UIWebViewNavigationTypeLinkClicked, we need to wait for a subsequent request of navigationType UIWebViewNavigationTypeOther, always (and always return NO on this first request, if not the NSURLProtocol handler will kick in and reject it anyway).

          If we don't receive the subsequent request (within a set interval) - we reject the request (return NO). If we receive the subsequent request, we process it for the whitelist normally.

          This will not apply to child iframes because we detect that the request is from an iframe, and iframe requests can load external urls (if they pass the whitelist). This proposed new policy only applies to the main page loaded by the UIWebView.

          Because of the complexity of this, this can't make it in 1.6.0

          Show
          Shazron Abdullah added a comment - There are two types of anchor tag requests: 1. Has no target attribute 2. Has a target attribute that should launch a new Mobile Safari window For request type (1), the UIWebViewDelegate gets one NSURLRequest with navigationType UIWebViewNavigationTypeLinkClicked For request type (2), the UIWebViewDelegate gets two NSURLRequests with the first being navigationType UIWebViewNavigationTypeLinkClicked, then the second with navigationType UIWebViewNavigationTypeOther It is this two request process that prevents this issue from being an easy fix - since at the first request, the NSURLRequest can be rejected before we can process it for the second request (which differentiates it at being target="_blank"), where it can be accepted. How do I differentiate between the two types of anchor tags then, to fix this issue? You can't, not easily. This would require saving state (the request) when a UIWebViewNavigationTypeLinkClicked navigationType is encountered, waiting for a set interval then seeing if a request with navigationType UIWebViewNavigationTypeOther follows suit. If it doesn't, process the NSURLRequest normally. If it does, punt it to Mobile Safari. This can potentially be error prone. I think what needs to happen is a change in the behaviour for handling anchor tags. Here's what I propose: If it's an anchor tag with NO target attribute - it can ONLY load file urls, no http urls. Thus only local files can be loaded in the UIWebView in this situation. If it's an anchor tag WITH a target attribute - it can ONLY load external http urls, no file urls (besides Mobile Safari won't display any file urls). Thus only external files can be loaded in Mobile Safari in this situation. With this new policy, all requests with navigationTypes of UIWebViewNavigationTypeLinkClicked, we need to wait for a subsequent request of navigationType UIWebViewNavigationTypeOther, always (and always return NO on this first request, if not the NSURLProtocol handler will kick in and reject it anyway). If we don't receive the subsequent request (within a set interval) - we reject the request (return NO). If we receive the subsequent request, we process it for the whitelist normally. This will not apply to child iframes because we detect that the request is from an iframe, and iframe requests can load external urls (if they pass the whitelist). This proposed new policy only applies to the main page loaded by the UIWebView. Because of the complexity of this, this can't make it in 1.6.0
          Hide
          Patrick Mueller added a comment -

          Clarification? When you say:

          If it's an anchor tag with NO target attribute - it can ONLY load file urls, no http urls. Thus only local files can be loaded in the UIWebView in this situation.

          If it's an anchor tag WITH a target attribute - it can ONLY load external http urls, no file urls (besides Mobile Safari won't display any file urls). Thus only external files can be loaded in Mobile Safari in this situation.

          Do you mean:

          • users must only use file urls with no target, and only use http urls with target?
          • iOS only allows you to use file urls with no target, and only http urls with target?

          If it's the 1st, it sounds like you are expecting to doc this behavior. What happens if they don't follow our guidance? Can we validate it somehow (seems unlikely)?

          I can certainly understand not allowing Mobile Safari to open file:// URLs. Do they allow that already? I don't understand not allowing an http URL to be loaded into a WebView.

          Does Android have all this same behavior?

          Does this just apply to target=_blank, or any <a target=>? What about the other magical targets? What about plain old user-named targets?

          Show
          Patrick Mueller added a comment - Clarification? When you say: If it's an anchor tag with NO target attribute - it can ONLY load file urls, no http urls. Thus only local files can be loaded in the UIWebView in this situation. If it's an anchor tag WITH a target attribute - it can ONLY load external http urls, no file urls (besides Mobile Safari won't display any file urls). Thus only external files can be loaded in Mobile Safari in this situation. Do you mean: users must only use file urls with no target, and only use http urls with target? iOS only allows you to use file urls with no target, and only http urls with target? If it's the 1st, it sounds like you are expecting to doc this behavior. What happens if they don't follow our guidance? Can we validate it somehow (seems unlikely)? I can certainly understand not allowing Mobile Safari to open file:// URLs. Do they allow that already? I don't understand not allowing an http URL to be loaded into a WebView. Does Android have all this same behavior? Does this just apply to target=_blank, or any <a target=>? What about the other magical targets? What about plain old user-named targets?
          Hide
          Shazron Abdullah added a comment -

          see also Andrew's blog post regarding current behaviour in Cordova: https://build.phonegap.com/blog/access-tags

          To be clear, iOS allows everything to happen within a UIWebView, load external as well as file urls that are in your app sandbox. On a iOS device, iOS restricts your app from loading a file url in Mobile Safari.

          Effectively - a file url anchor tag with target doesn't work anyway according to iOS' restrictions so this is a documentation issue.

          A http url with or without target is within what we can control. With target, that's easy, we punt it to Mobile Safari. Without target, the current behaviour is to load it into UIWebView, replacing the existing page that the anchor tag is in - my fix proposal is we don't do this.

          If an external webpage takes over the UIWebView, how would you get "back" to your app? Are there scenarios where people do this or this is desired? Note that my proposal will not affect loading http urls in iFrames.

          From my tests, any anchor target value will trigger a new request, with its UIWebViewNavigationType as UIWebViewNavigationTypeOther which Apple defines as "Some other action occurred." in their docs for UIWebView (not really helpful), thus there is no way to differentiate between "_self" or "_blank". We are treating any target value as "_blank" effectively.

          Android and Blackberry behaviour is listed in the link I put at the start of this comment. Looking at that table in the link, this proposed fix (the only fix I can think of to solve this issue) is to correct the "unlisted" behaviour of iOS. But, in doing so, it will alter the expectations of the "whitelisted" column for iOS.

          With the proposed fix:
          Regular link – changes from "webview" to "webview (file urls only)"
          target="_blank" – stays the same as "browser" (file urls can't be opened in the browser anyway - iOS restriction)

          The problem with my proposed fix is it will change expected behaviour across all the platforms (ie iOS does it this way, but Android does it that way), thus it is high risk and against the project's philosophy, which suggests to me that this issue is a "won't fix".

          Show
          Shazron Abdullah added a comment - see also Andrew's blog post regarding current behaviour in Cordova: https://build.phonegap.com/blog/access-tags To be clear, iOS allows everything to happen within a UIWebView, load external as well as file urls that are in your app sandbox. On a iOS device, iOS restricts your app from loading a file url in Mobile Safari. Effectively - a file url anchor tag with target doesn't work anyway according to iOS' restrictions so this is a documentation issue. A http url with or without target is within what we can control. With target, that's easy, we punt it to Mobile Safari. Without target, the current behaviour is to load it into UIWebView, replacing the existing page that the anchor tag is in - my fix proposal is we don't do this. If an external webpage takes over the UIWebView, how would you get "back" to your app? Are there scenarios where people do this or this is desired? Note that my proposal will not affect loading http urls in iFrames. From my tests, any anchor target value will trigger a new request, with its UIWebViewNavigationType as UIWebViewNavigationTypeOther which Apple defines as "Some other action occurred." in their docs for UIWebView (not really helpful), thus there is no way to differentiate between "_self" or "_blank". We are treating any target value as "_blank" effectively. Android and Blackberry behaviour is listed in the link I put at the start of this comment. Looking at that table in the link, this proposed fix (the only fix I can think of to solve this issue) is to correct the "unlisted" behaviour of iOS. But, in doing so, it will alter the expectations of the "whitelisted" column for iOS. With the proposed fix: Regular link – changes from "webview" to "webview (file urls only)" target="_blank" – stays the same as "browser" (file urls can't be opened in the browser anyway - iOS restriction) The problem with my proposed fix is it will change expected behaviour across all the platforms (ie iOS does it this way, but Android does it that way), thus it is high risk and against the project's philosophy, which suggests to me that this issue is a "won't fix".
          Hide
          Patrick Mueller added a comment -

          Ah, thanks for the additional info.

          Seems to me that whatever behavior we provide could be 'overridden' by an app, if provided a behavior override setting. While there's prolly little reason to actually expose such a thing today, perhaps you could at least arrange the code with this in mind.

          I wonder how many people doing this anyway - I never do anything but single-page apps for mobile. Never use external links. For chrome-less web apps (save to "home screen"), it's easy to get screwed. You get into a black hole where (as you pointed out) you have no way of going out, if you load an external page (I've seen this happen, but can't remember how I made it happen). And when you shell out to Mobile Safari, then you'll have to restart your app to get back to it.

          Show
          Patrick Mueller added a comment - Ah, thanks for the additional info. Seems to me that whatever behavior we provide could be 'overridden' by an app, if provided a behavior override setting. While there's prolly little reason to actually expose such a thing today, perhaps you could at least arrange the code with this in mind. I wonder how many people doing this anyway - I never do anything but single-page apps for mobile. Never use external links. For chrome-less web apps (save to "home screen"), it's easy to get screwed. You get into a black hole where (as you pointed out) you have no way of going out, if you load an external page (I've seen this happen, but can't remember how I made it happen). And when you shell out to Mobile Safari, then you'll have to restart your app to get back to it.
          Hide
          Richard Kimber added a comment -

          It had never actually occurred to me to use an anchor to do anything other than spawn an external app (i.e. dialer, mail, maps or browser). As Patrick says, I assumed the default was a single app with JavaScript navigation.

          Can this not be achieved cross device through the JavaScript API?

          Rich

          Show
          Richard Kimber added a comment - It had never actually occurred to me to use an anchor to do anything other than spawn an external app (i.e. dialer, mail, maps or browser). As Patrick says, I assumed the default was a single app with JavaScript navigation. Can this not be achieved cross device through the JavaScript API? Rich
          Hide
          Shazron Abdullah added a comment -

          @Richard Yup, this really should be through an API function so it's unambiguous.

          Show
          Shazron Abdullah added a comment - @Richard Yup, this really should be through an API function so it's unambiguous.
          Hide
          Andrew Lunny added a comment -

          I talked with Shaz about this offline; here's a summary of what I think

          • we should have an API function for "open page in browser" that ignores the whitelist entirely. Links to whitelisted domains should open in the webview.
          • (more contentious) I think links to untrusted domains should always launch the browser. If you don't like this, use ChildBrowser to intercept the click/touch events, or don't put links to untrusted domains in your app.
          • ignore target and UIWebViewNavigationTypeOther. A lot of extra complexity, and it won't work cross platform anyway
          • all iframe/XHR calls should be locked to the whitelist. This change would only affect "a" tags.
          Show
          Andrew Lunny added a comment - I talked with Shaz about this offline; here's a summary of what I think we should have an API function for "open page in browser" that ignores the whitelist entirely. Links to whitelisted domains should open in the webview. (more contentious) I think links to untrusted domains should always launch the browser. If you don't like this, use ChildBrowser to intercept the click/touch events, or don't put links to untrusted domains in your app. ignore target and UIWebViewNavigationTypeOther. A lot of extra complexity, and it won't work cross platform anyway all iframe/XHR calls should be locked to the whitelist. This change would only affect "a" tags.
          Hide
          Shazron Abdullah added a comment -

          Punting to 1.8.0 since this requires a multi-platform discussion still

          Show
          Shazron Abdullah added a comment - Punting to 1.8.0 since this requires a multi-platform discussion still
          Hide
          Randy McMillan added a comment -

          -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
          {
          NSURL *requestURL =[ [ request URL ] retain ];
          if ( ( [ [ requestURL scheme ] isEqualToString: @"http" ] || [ [ requestURL scheme ] isEqualToString: @"https" ] || [ [ requestURL scheme ] isEqualToString: @"mailto" ])
          && ( navigationType == UIWebViewNavigationTypeLinkClicked ) )

          { return ![ [ UIApplication sharedApplication ] openURL: [ requestURL autorelease ] ]; }


          [ requestURL release ];
          return YES;
          }

          Adding this to the MainViewController.m works perfect. (Unless Ive missed something).

          Submitted pull request https://github.com/apache/incubator-cordova-ios/pull/19

          Show
          Randy McMillan added a comment - -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; { NSURL *requestURL =[ [ request URL ] retain ]; if ( ( [ [ requestURL scheme ] isEqualToString: @"http" ] || [ [ requestURL scheme ] isEqualToString: @"https" ] || [ [ requestURL scheme ] isEqualToString: @"mailto" ]) && ( navigationType == UIWebViewNavigationTypeLinkClicked ) ) { return ![ [ UIApplication sharedApplication ] openURL: [ requestURL autorelease ] ]; } [ requestURL release ]; return YES; } Adding this to the MainViewController.m works perfect. (Unless Ive missed something). Submitted pull request https://github.com/apache/incubator-cordova-ios/pull/19
          Hide
          Randy McMillan added a comment -

          It may need further testing but when added to the MainViewController.m the

          <a target="_blank" href="http://docs.phonegap.com/en/edge/guide_getting-started_ios_index.md.html#Getting%20Started%20with%20iOS">Getting Started Guide</a>

          opens in Safari with no other modifications to the xcode project.

          Show
          Randy McMillan added a comment - It may need further testing but when added to the MainViewController.m the <a target="_blank" href="http://docs.phonegap.com/en/edge/guide_getting-started_ios_index.md.html#Getting%20Started%20with%20iOS">Getting Started Guide</a> opens in Safari with no other modifications to the xcode project.
          Hide
          Randy McMillan added a comment -

          tested link provided in the description as well.

          Show
          Randy McMillan added a comment - tested link provided in the description as well.
          Hide
          Randy McMillan added a comment -

          I clicked the generic

          <a href="http://www.sencha.com/products/touch" target="blank">sencha.com/products/touch</a>

          located at the bottom of the Main.js screen to test as well.

          Show
          Randy McMillan added a comment - I clicked the generic <a href="http://www.sencha.com/products/touch" target="blank">sencha.com/products/touch</a> located at the bottom of the Main.js screen to test as well.
          Hide
          Randy McMillan added a comment -

          _self loads the link into the webView when link added to whitelist. (respects whitelist)

          _blank loads in safari independent of whitelist.

          I believe this is the desired functionality.

          Show
          Randy McMillan added a comment - _self loads the link into the webView when link added to whitelist. (respects whitelist) _blank loads in safari independent of whitelist. I believe this is the desired functionality.
          Hide
          Randy McMillan added a comment -

          Q. Is it something im doing or is there lag between the apache repo image and the github repo image?

          Show
          Randy McMillan added a comment - Q. Is it something im doing or is there lag between the apache repo image and the github repo image?
          Hide
          Randy McMillan added a comment -

          reference

          phonegap.com.both.png
          phonegap.png

          _self and _blank on the same domain have desired functionality.

          Show
          Randy McMillan added a comment - reference phonegap.com.both.png phonegap.png _self and _blank on the same domain have desired functionality.
          Hide
          Randy McMillan added a comment - - edited

          -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
          {
          NSURL *requestURL =[ [ request URL ] retain ];
          if ( ( [ [ requestURL scheme ] isEqualToString: @"http" ] || [ [ requestURL scheme ] isEqualToString: @"https" ] || [ [ requestURL scheme ] isEqualToString: @"mailto" ])
          && ( navigationType == UIWebViewNavigationTypeOther ) )

          { return ![ [ UIApplication sharedApplication ] openURL: [ requestURL autorelease ] ]; }


          [ requestURL release ];
          return YES;
          }

          Further testing indicates that the above provides the desired functionality of using _self and _blank on the same domain.

          Show
          Randy McMillan added a comment - - edited -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; { NSURL *requestURL =[ [ request URL ] retain ]; if ( ( [ [ requestURL scheme ] isEqualToString: @"http" ] || [ [ requestURL scheme ] isEqualToString: @"https" ] || [ [ requestURL scheme ] isEqualToString: @"mailto" ]) && ( navigationType == UIWebViewNavigationTypeOther ) ) { return ![ [ UIApplication sharedApplication ] openURL: [ requestURL autorelease ] ]; } [ requestURL release ]; return YES; } Further testing indicates that the above provides the desired functionality of using _self and _blank on the same domain.
          Show
          Randy McMillan added a comment - https://github.com/RandyMcMillan/openInSafari
          Hide
          Olivier Louvignes added a comment - - edited

          There is also the "tel:" & "maps:" schemes that should correctly be handled, works so far (maybe with a wildcard in ExternalHost) don't know if it's the case with this patch but the code above does not use them, it could be a possible regression.

          Show
          Olivier Louvignes added a comment - - edited There is also the "tel:" & "maps:" schemes that should correctly be handled, works so far (maybe with a wildcard in ExternalHost) don't know if it's the case with this patch but the code above does not use them, it could be a possible regression.
          Hide
          Randy McMillan added a comment - - edited

          -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
          {
          NSURL *requestURL =[ [ request URL ] retain ];
          if ( ( [ [ requestURL scheme ] isEqualToString: @"http" ] || [ [ requestURL scheme ] isEqualToString: @"https" ] || [ [ requestURL scheme ] isEqualToString: @"mailto" ] || [ [ requestURL scheme ] isEqualToString: @"tel" ] || [ [ requestURL scheme ] isEqualToString: @"maps" ])
          && ( /navigationType == UIWebViewNavigationTypeLinkClicked ||/ navigationType == UIWebViewNavigationTypeOther ) )

          { return ![ [ UIApplication sharedApplication ] openURL: [ requestURL autorelease ] ]; }


          [ requestURL release ];
          return YES;
          }

          adding tel to the switch works. (didnt test maps)

          tested using

          <a href="tel:+1-800-275-2273">
          Call Apple Customer Support at 1-800-275-2273
          </a>

          Show
          Randy McMillan added a comment - - edited -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; { NSURL *requestURL =[ [ request URL ] retain ]; if ( ( [ [ requestURL scheme ] isEqualToString: @"http" ] || [ [ requestURL scheme ] isEqualToString: @"https" ] || [ [ requestURL scheme ] isEqualToString: @"mailto" ] || [ [ requestURL scheme ] isEqualToString: @"tel" ] || [ [ requestURL scheme ] isEqualToString: @"maps" ]) && ( / navigationType == UIWebViewNavigationTypeLinkClicked || / navigationType == UIWebViewNavigationTypeOther ) ) { return ![ [ UIApplication sharedApplication ] openURL: [ requestURL autorelease ] ]; } [ requestURL release ]; return YES; } adding tel to the switch works. (didnt test maps) tested using <a href="tel:+1-800-275-2273"> Call Apple Customer Support at 1-800-275-2273 </a>
          Hide
          Shazron Abdullah added a comment -

          Punting to 2.0.0 since this will be a breaking change. Discussion plus a decision still needs to be done on what to do.

          Show
          Shazron Abdullah added a comment - Punting to 2.0.0 since this will be a breaking change. Discussion plus a decision still needs to be done on what to do.
          Hide
          Mike Flores added a comment -

          Good News: child browser does not exhibit bug on Samsung Galaxy Tab 10.1 running Android 3.0, Honeycomb.
          Upon tapping the return arrow on the device, the page returns to parent browser that spawned child browser which is the correct behavior.
          iOS 5 also works fine. Android 2.1 through 2.33 and Android 4.x have this bug. I don't believe PhoneGap jar is at fault for this bug.

          Show
          Mike Flores added a comment - Good News: child browser does not exhibit bug on Samsung Galaxy Tab 10.1 running Android 3.0, Honeycomb. Upon tapping the return arrow on the device, the page returns to parent browser that spawned child browser which is the correct behavior. iOS 5 also works fine. Android 2.1 through 2.33 and Android 4.x have this bug. I don't believe PhoneGap jar is at fault for this bug.
          Hide
          Shazron Abdullah added a comment -

          Consensus in the mailing list is to include the ChildBrowser plugin into core.

          Show
          Shazron Abdullah added a comment - Consensus in the mailing list is to include the ChildBrowser plugin into core.
          Hide
          Brian LeRoux added a comment -

          true; but whats wrong w/ the solution proposed by randy?

          Show
          Brian LeRoux added a comment - true; but whats wrong w/ the solution proposed by randy?
          Hide
          Shazron Abdullah added a comment -

          Don't want to have to explain it again, frankly no one has understood the problem – we've already discussed this, see my FIRST comment in this issue. It is the two request problem, the whitelist prevents any of Randy's solutions from working - the request gets rejected at the first request.

          Show
          Shazron Abdullah added a comment - Don't want to have to explain it again, frankly no one has understood the problem – we've already discussed this, see my FIRST comment in this issue. It is the two request problem, the whitelist prevents any of Randy's solutions from working - the request gets rejected at the first request.
          Hide
          Shazron Abdullah added a comment -

          The InAppBrowser (was ChildBrowser) feature would fix this: http://wiki.apache.org/cordova/InAppBrowser

          Show
          Shazron Abdullah added a comment - The InAppBrowser (was ChildBrowser) feature would fix this: http://wiki.apache.org/cordova/InAppBrowser
          Hide
          Shazron Abdullah added a comment -

          Once we have InAppBrowser tasks (cross-platform) we should close this and refer to that task.

          Show
          Shazron Abdullah added a comment - Once we have InAppBrowser tasks (cross-platform) we should close this and refer to that task.
          Hide
          Shazron Abdullah added a comment -

          Will be resolved in CB-1507 for iOS (CB-1506 for all platforms)

          Show
          Shazron Abdullah added a comment - Will be resolved in CB-1507 for iOS ( CB-1506 for all platforms)

            People

            • Assignee:
              Shazron Abdullah
              Reporter:
              Andrew Lunny
            • Votes:
              5 Vote for this issue
              Watchers:
              10 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development