I am facing an issue in an iOS application that uses a UIWebView to render HTML5 code that is part of the application bundle.
This HTML5 code makes ajax requests to our backend which may potentially have sensitive data in them. This is all done over HTTPS and our application never stores the sensitive data. However, when doing security testing for the application, we found that http post requests where being stored in a local SQL Lite database (cache.db) as of iOS 5.
It was easy to manage that, by setting the NSURLCache global object to have zero disk storage, and deleting the file when appropriate.
Now however, it looks like in iOS 6.1 Apple has changed the implementation again, and the data is being stored in cache.db-wal. I have limited knowledge of SQL Lite, but I think this is a file created when SQL Lite is initialized with certain options.
Any suggestions as to a fix?
After further research, it seems that the suggestion by Hot Licks above was correct, by adding the "no-cache, no-store" value to the HTTP response, the HTTP request values where not logged in the SQLite database.
For example, in ASP.Net MVC:
public ActionResult PostSensitiveData(string data)
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();
return Json(data);
}
The other files created by SQLite (-journal, -wal, -shm) are part of the database itself.
When you delete the cache.db file, also delete any cache.db-* files.
To prevent that data gets inserted in the first place, open the database and create some trigger like this on every table:
CREATE TRIGGER MyTable_evil_trigger
BEFORE INSERT ON MyTable
BEGIN
SELECT RAISE(IGNORE);
END;
(And then check whether the UIWebView blows up when the inserted records don't actually show up …)
You can call
[[NSURLCache sharedURLCache] removeAllCachedResponses]
This will clear all the cached url calls from the Cache.db file.
I struggled on the same issue. Since I was using react-native, I felt that the current answer were inconvenient.
So, I came up with two solutions:
Use this package
https://github.com/qq273335649/oa-react-native-clear-cache
Then using the function clearCache. The problem is that it erases all the cache, not necessarily convenient.
After the queries that saves the confidential data in the cache, I remove the db-wal file with the package expo-file-system (you need to be using expo for this one)
I hope it helps.
Related
In an app I'm building, I'm using Core Data to cache remote content from an API for offline viewing. This all works pretty well except for one big issue: if a record on the server is deleted there's no way for me to detect that and delete its cached counterpart.
The only thing I can think of is somehow marking all the current data as 'invalid' when I pull data from the API and only mark the records returned by the API as valid again, but it seems like this is a clunky solution to the problem. Additionally, as data from the API I'm using is paginated it doesn't scale well for lots of records.
So what I want to know is: is there a better way to invalidate local cache data in response to it being deleted server-side?
I would suggest, although not the easiest route, is to have the server side cache items that are deleted and expose an endpoint you can call to get the deleted items. In a perfect world right.
What you can do is in a background thread, download all the data from the server and compare it to what you have locally. So instead of just invalidating all of it and re-parsing it back in (which can take time for large data sets), just run through and compare id's of objects on the server to your objects in CoreData. If it's there great, if not delete it from you local db. Hope this helps.
Is there a way to query the contents of the HTML5 application cache?
I'm writing an iOS application that uses a lot of cached web content. Before loading a given page when the app is offline, I'd like to check whether the page exists in the cache. If it doesn't, I'll notify the user that they have to be online to see that content; if it does, I'll go ahead and load it.
Now, iOS has its own URL caching system, and I initially just assumed that I could check the contents of the cache this way:
if ([[NSURLCache sharedURLCache] cachedResponseForRequest:myRequest] != nil) {
// go ahead and load the page
}
else {
// notify the user that the content isn't available
}
Silly me. It seems that iOS's cache and HTML5's cache are unrelated: -cachedResponseForRequest: returns nil for any request, even when I can see that the URL is in the HTML5 application cache (using the Safari web debugger).
So, is there some way that I can query the contents of the HTML5 application cache? It doesn't matter if the answer uses Objective-C code or Javascript, since I can always just execute the relevant JS from Objective-C.
There are two properties of HTML5 AppCache which mean that in normal operation there shouldn't be a need to do so:
AppCache update operations are atomic, either the entire cache is updated, or none of it it
Once an AppCache is created then all files that are in the cache are served from the cache
The end result is that for any given version of the manifest file, any file listed in it that gets loaded into the browser will be consistent with all the other files listed in the manifest. All you should need to check is window.applicationCache.status and check that it is not UNCACHED.
There is another possibility. If you are 'lazily adding' files to the AppCache as described in Dive Into HTML5 then it could be that you're not sure which files are cached. In this case you could adapt one of the approaches for detecting online state, I'm not going to give you a fully tested solution but here is the general idea:
Create a web page containing a unique identifier, something that's unlikely to ever appear normally in a page. The identifier can be in hidden content in an otherwise normal page.
Set this page as the generic FALLBACK in your manifest.
Request pages with AJAX.
Scan the response for the unique identifier, if you find it then you know the page requested is not in the AppCache
Yes,the cache is stored in the Application.db.
I have a system I've built in MVC 3 that currently provides a yearly submission cycle where the system proceeds through a serious of seven steps tied to dates stored in the web.config as AppSettings. However, each year, I always have to roll the system back and forth between previous steps in order to accommodate the end users. I would like to give the administrator the ability to control the system status without having to contact a developer. What is the best way to do this?
I plan to build a page with proper validation that lets the administrator set the dates. I've considered a couple options of how I should store those date, but none of them seem correct. Our entire permission system uses these dates, and various bits of text on the pages turns on and off based on what period we're currently in.
So far I've come up with two options:
Option 1: Create a database table – This was my first thought. I’ve set up properties on the MvcApplication class in the global.asax and pulled them from the database. Using a lazy loader, I can set the properties the first time they're needed. However, when they change in the database, I don't have a way to force the system to “reset” and read the date changes. If I do this action on Begin_Request(), I'm constantly opening the connection and resetting the properties for each file that the web browser opens on the server, regardless if it's static content or not.
I could directly fetch the dates from the database every time I need one of the dates, but then I'm having to redo a lot of functionality to reduce repeated database calls. I'd like to cache the dates for each request, and only pull them when I need them,
Option 2: Allow editing a config file through the application – I've looked up how to split the web.config file so I can have a separate file that just contains the appSettings. Then I could just update the new config file from a controller action. I think this would work nicely, and not require me to rewrite any of the existing functionality, but it feels like I would be introducing a bad design pattern into the code.
I'd vote for the database. For the sake of performance you can cache those parameter values in a static class inside your app and provide a method to reread them from DB in the same class. So:
When a user makes request, check if those properties are already cached. If they are - use cached values, if no - read them from DB
When administrator makes changes to those parameters - store them to database and enforce your static caching class to reread them from DB.
I would suggest an approach that doesn't care whether the settings are stored in database or key/value pairs in config file.
Since you want the settings to be accessed globally by all users you can cache the settings and the cache implementation should be generic and distributed. There are plenty of online resources available how to create such an interface.
Since you want the cache to be sync with the underlying data you have to set cache dependencies (AppFabric won't supports sql cache dependency see this thread, while NCache supports both sql and file).
I would store the values in a database and use a distributed cache to persist the data across the web farm. MS AppFabric Caching has worked well for me. You will need to implement a standard caching pattern (check the cache, if null load from db and insert into cache).I would probably just create a static Load() method that abstracts this logic away. When the admins update the db you could update the cache or just delete the cachekey.
Therr are other considerations to be added to performance. Namely if you modify the config file thr application pool is re iniyializrd, while the database solution doesnt cause application reinitialization
...so do you need to re initialize the app after the changes or not?...If there i no way to avoid the inizialization whitout drastic changmes to the application ptobably the config filr solution is better
I'm about to write a simple iPhone app that uses Core Data to store local copy of remote data that is fetched via RESTful web service. The data changes (new records being added) quite often. I came across RestKit and I'm wondering if it can do what I need. And what I need is to load all records in the beginning and then periodically download ONLY records that were added since previous check. Obviously there is no mystery about how that can be accomplished even by simply using NSURLConnection, but I hoped RestKit (probably in combination with a proper web service) would do that without me having to write all the synchronization logic. Again the key for me is that only new/changed data is fetched from the server.
I agree - RestKit can do this, we've recently used it to do something similar in a recent project. We used a last-modified-date request header to indicate the last successful 'sync' time, which the server can use to return only the records modified since that date. A http 304 'not modified' status code was used to indicate no change when appropriate.
RestKit also includes a seeding facility, so you know up front the initial data set - you can seed it as the initial database easily, and fetch the updates, even upon first use of the application.
Some information I found useful regarding RestKit & CoreData mapping - https://github.com/RestKit/RestKit/blob/master/Docs/Object%20Mapping.md, and the Google group is a good source as well - https://groups.google.com/group/restkit. Hope this all helps.
First of all: YES
RestKit handles CoreData very well. All you need to do is to provide mapping of your entities and it does the work for you.
For the second thing about selective sync, I really recommend checking StorageRoomApp it is a great, and not so expensive service that does exactly what you need.
They have a very good API that extends RestKit, it is very easy to use and their support is great. Take a look.
I am currently building an iPhone app that is using Core Data and sqlite databases where the user will be reading static information from the database throughout the app. I have the issue where we may update the information in the database but not want to do a full update of the app, just the database. Can someone please help me out with either a easy function or a tutorial of how to go to a website or server and download the file which will replace the database that we have already put into the app? I'm new in xcode and I`m doing my first app.... thanks for your help
I think what would be a good idea is for your website to publish the data that must be stored in sqllite over REST, possibly in JSON or XML format.
This blog post describes how you could do just that. I must say that its approach to retrieving the content from the webservice is kind of low-level but it'll get the job done. Maybe RestKit can help you take care of all the low-level networking/http stuff.
I assume you want the static data locally so you don't require a constant internet connection for your app to work. Another option is to request the static data from the web and persist it in a file (NSUserDefaults etc...). But, that depends on how complicated the static data is and whether you have to query into that data. If you need to issue queries on that static data, a DB is definitely better.
You can also do a combination where you download updated DB if available async while your app works. You could have a setting in user defaults which is the current static data DB. If updated, you switch the current setting and re-establish the DB connection under a lock.
Here's how to make an http request using iOS.
rest web services in iphone
If you're downloading db data, don't convert the NSData to a string like in that sample ...
Also, ASI-HTTP-Request is popular. Here's samples on how to download a file:
http://allseeing-i.com/ASIHTTPRequest/How-to-use
http://www.cocoadev.com/index.pl?NSUserDefaults