I have a client that retrieves a certificate (.pfx), including a private key, from a server and I add this to the local keychain with the following code: -
void AddCertToKeyChain(const QByteArray& cert, const QString& password)
{
SecKeychainRef keyChain = nil;
OSStatus err = SecKeychainCopyDomainDefault(kSecPreferencesDomainUser, &keyChain);
if (err != errSecSuccess)
{
emit Log("Failed to access system keychain: " + LogMessageForStatus(err));
return;
}
SecExternalFormat format = kSecFormatPKCS12;
SecExternalItemType itemType = kSecItemTypeAggregate;
SecItemImportExportFlags flags = 0;
SecItemImportExportKeyParameters params;
memset(¶ms, 0, sizeof(params));
params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
params.flags = 0;
params.passphrase = password.toCFString();
params.alertTitle = NULL;
params.alertPrompt = NULL;
params.accessRef = NULL;
// create and populate the key usage array
CFMutableArrayRef keyUsage = CFArrayCreateMutable(
kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks
);
CFArrayAppendValue(keyUsage, kSecAttrCanEncrypt);
CFArrayAppendValue(keyUsage, kSecAttrCanDecrypt);
CFArrayAppendValue(keyUsage, kSecAttrCanDerive);
CFArrayAppendValue(keyUsage, kSecAttrCanSign);
CFArrayAppendValue(keyUsage, kSecAttrCanVerify);
CFArrayAppendValue(keyUsage, kSecAttrCanWrap);
CFArrayAppendValue(keyUsage, kSecAttrCanUnwrap);
keyUsage = NULL; // Error without this - Failed to import certificate: The key usage mask is not supported.
// create and populate the key attributes array
CFMutableArrayRef keyAttributes = CFArrayCreateMutable(
kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks
);
// required for import
params.keyUsage = keyUsage;
params.keyAttributes = keyAttributes;
OSStatus status = SecItemImport(cert.toCFData(), CFSTR(".p12"), &format, &itemType, flags, ¶ms, keyChain, NULL);
if(status == errSecSuccess)
emit Log("Certificate successfully imported");
else
{
emit Log("Failed to import certificate: " + LogMessageForStatus(status));
}
}
The certificate and private key appear in the keychain, as expected.
However, trying to retrieve the certificate is a problem, either programmatically or using the Keychain application.
If I select to export the private key from the keychain, I'm provided with the following error in a dialog: -
"An error has occurred. Unable to export an item. The contents of this item cannot be retrieved"
However, if the certificate and key are added to the keychain by double-clicking on the pfx, exporting the key works as expected.
So, why would the code above cause the problem of not being able to export the key?
With the assistance of Quinn at Apple, It seems that the method described in the question should work, but doesn't.
Using an old CDSA style flag instead does in fact work, doing something like this: -
OSStatus err;
SecExternalFormat format;
SecItemImportExportKeyParameters params;
params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
params.flags = 0;
params.passphrase = (__bridge CFStringRef) pkcs12Password;
params.alertTitle = NULL;
params.alertPrompt = NULL;
params.accessRef = NULL;
params.keyUsage = NULL;
params.keyAttributes = (__bridge CFArrayRef) #[ #(CSSM_KEYATTR_EXTRACTABLE) ];
format = kSecFormatPKCS12;
err = SecItemImport(
(__bridge CFDataRef) pkcs12Data,
CFSTR("p12"),
&format,
NULL,
0,
¶ms,
keychain,
NULL
);
Note the setting of params.keyAttributes, which defines the key to be extractable.
Alternatively, the older (deprecated) SecKeychainItemImport API may be used: -
BOOL success;
OSStatus err;
NSArray * result;
SecExternalFormat format;
SecKeyImportExportParameters params;
CFArrayRef importedItems;
result = nil;
importedItems = NULL;
format = kSecFormatPKCS12;
memset(¶ms, 0, sizeof(params));
params.passphrase = password;
params.keyAttributes = CSSM_KEYATTR_EXTRACTABLE;
err = SecKeychainItemImport(
(CFDataRef) pkcs12Blob, // importedData
NULL, // fileNameOrExtension
&format, // inputFormat
NULL, // itemType
0, // flags
¶ms, // keyParams
self->keychain, // importKeychain
&importedItems // outItems
);
success = (err == noErr);
While the function SecKeychainItemImport is defined as deprecated in Apple's documentation, I have been informed that it's unlikely to be removed any time soon.
Related
The following code creates and initialises a simple progress bar using CFUserNotification API. How would I add a callback to update the progress bar ? With this code, the progress is at the constant value indicated by prog.
float prog = 0.1;
CFNumberRef cfNum = CFNumberCreate(kCFAllocatorDefault,kCFNumberFloatType, &prog);
const void* keys[] = { kCFUserNotificationAlertHeaderKey, kCFUserNotificationProgressIndicatorValueKey };
const void* vals[] = { CFSTR("Progress Bar"), cfNum};
CFDictionaryRef dict = CFDictionaryCreate(0, keys, vals,
sizeof(keys)/sizeof(*keys),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFUserNotificationRef pDlg = NULL;
pDlg = CFUserNotificationCreate(kCFAllocatorDefault, 0,
kCFUserNotificationPlainAlertLevel,
&nRes, dict);
I want to import data from Excel files into SQL Server. The size of the file is 22 MB and contains approximately 1 million rows, but I get the error timeout.
This is the code of my controller
[System.Web.Http.Route("UploadExcel")]
[System.Web.Http.HttpPost]
[RequestFormLimits(MultipartBodyLengthLimit = 409715200)]
[RequestSizeLimit(409715200)]
public string ExcelUpload()
{
string message = "";
HttpResponseMessage result = null;
var httpRequest = HttpContext.Current.Request;
using (AngularDBEntities objEntity = new AngularDBEntities())
{
if (httpRequest.Files.Count > 0)
{
HttpPostedFile file = httpRequest.Files[0];
Stream stream = file.InputStream;
IExcelDataReader reader = null;
if (file.FileName.EndsWith(".xls"))
{
reader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else if (file.FileName.EndsWith(".xlsx"))
{
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
}
else
{
message = "This file format is not supported";
}
DataSet excelRecords = reader.AsDataSet();
reader.Close();
var finalRecords = excelRecords.Tables[0];
for (int i = 0; i < finalRecords.Rows.Count; i++)
{
UserDetail objUser = new UserDetail();
objUser.UserName = finalRecords.Rows[i][0].ToString();
objUser.EmailId = finalRecords.Rows[i][1].ToString();
objUser.Gender = finalRecords.Rows[i][2].ToString();
objUser.Address = finalRecords.Rows[i][3].ToString();
objUser.MobileNo = finalRecords.Rows[i][4].ToString();
objUser.PinCode = finalRecords.Rows[i][5].ToString();
objEntity.UserDetails.Add(objUser);
}
int output = objEntity.SaveChanges();
if (output > 0)
{
message = "Excel file has been successfully uploaded";
}
else
{
message = "Excel file uploaded failed";
}
}
else
{
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
return message;
}
I added maxRequestLength="1048576" executionTimeout="999999" to the web.config file in the system.web section, and maxAllowedContentLength="1073741824" to security tag, but I am still facing this problem.
Knowing that when I upload small files, the data is added to the table
you can add all items in a list and finally use bulk insert. use can use Entity Framework Extensions.
I am trying to build a query parser by ranking the passages containing the terms.
I understand that I need to use SpanNearQuery, but I can't find a way to access Spans even after going through the documentation. The method I got returns null.
I have read https://lucidworks.com/blog/2009/07/18/the-spanquery/ which explains in a good way about the query. This explains how to access spans, but it is for solr 4.0 and unfortunately solr 6.3 doesn't have atomic reader any more.
How can I get the actual spans?
public void process(ResponseBuilder rb) throws IOException {
SolrParams params = rb.req.getParams();
log.warn("in Process");
if (!params.getBool(COMPONENT_NAME, false)) {
return;
}
Query origQuery = rb.getQuery();
// TODO: longer term, we don't have to be a span query, we could re-analyze the document
if (origQuery != null) {
if (origQuery instanceof SpanNearQuery == false) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"Illegal query type. The incoming query must be a Lucene SpanNearQuery and it was a " + origQuery.getClass().getName());
}
SpanNearQuery sQuery = (SpanNearQuery) origQuery;
SolrIndexSearcher searcher = rb.req.getSearcher();
IndexReader reader = searcher.getIndexReader();
log.warn("before leaf reader context");
List<LeafReaderContext> ctxs = (List<LeafReaderContext>) reader.leaves();
log.warn("after leaf reader context");
LeafReaderContext ctx = ctxs.get(0);
SpanWeight spanWeight = sQuery.createWeight(searcher, true);
Spans spans = spanWeight.getSpans(ctx, SpanWeight.Postings.POSITIONS);
AtomicReader wrapper = SlowCompositeReaderWrapper.wrap(reader);
Map<Term, TermContext> termContexts = new HashMap<Term, TermContext>();
Spans spans = fleeceQ.getSpans(wrapper.getContext(), new Bits.MatchAllBits(reader.numDocs()), termContexts);
// SpanWeight.Postings[] postings= SpanWeight.Postings.values();
// Spans spans = sQuery.getSpans();
// Assumes the query is a SpanQuery
// Build up the query term weight map and the bi-gram
Map<String, Float> termWeights = new HashMap<String, Float>();
Map<String, Float> bigramWeights = new HashMap<String, Float>();
createWeights(params.get(CommonParams.Q), sQuery, termWeights, bigramWeights, reader);
float adjWeight = params.getFloat(ADJACENT_WEIGHT, DEFAULT_ADJACENT_WEIGHT);
float secondAdjWeight = params.getFloat(SECOND_ADJ_WEIGHT, DEFAULT_SECOND_ADJACENT_WEIGHT);
float bigramWeight = params.getFloat(BIGRAM_WEIGHT, DEFAULT_BIGRAM_WEIGHT);
// get the passages
int primaryWindowSize = params.getInt(OWLParams.PRIMARY_WINDOW_SIZE, DEFAULT_PRIMARY_WINDOW_SIZE);
int adjacentWindowSize = params.getInt(OWLParams.ADJACENT_WINDOW_SIZE, DEFAULT_ADJACENT_WINDOW_SIZE);
int secondaryWindowSize = params.getInt(OWLParams.SECONDARY_WINDOW_SIZE, DEFAULT_SECONDARY_WINDOW_SIZE);
WindowBuildingTVM tvm = new WindowBuildingTVM(primaryWindowSize, adjacentWindowSize, secondaryWindowSize);
PassagePriorityQueue rankedPassages = new PassagePriorityQueue();
// intersect w/ doclist
DocList docList = rb.getResults().docList;
log.warn("Before Spans");
while (spans.nextDoc() != Spans.NO_MORE_DOCS) {
// build up the window
log.warn("Iterating through spans");
if (docList.exists(spans.docID())) {
tvm.spanStart = spans.startPosition();
tvm.spanEnd = spans.endPosition();
// tvm.terms
Terms terms = reader.getTermVector(spans.docID(), sQuery.getField());
tvm.map(terms, spans);
// The entries map contains the window, do some ranking of it
if (tvm.passage.terms.isEmpty() == false) {
log.debug("Candidate: Doc: {} Start: {} End: {} ", new Object[] { spans.docID(), spans.startPosition(), spans.endPosition() });
}
tvm.passage.lDocId = spans.docID();
tvm.passage.field = sQuery.getField();
// score this window
try {
addPassage(tvm.passage, rankedPassages, termWeights, bigramWeights, adjWeight, secondAdjWeight, bigramWeight);
} catch (CloneNotSupportedException e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Internal error cloning Passage", e);
}
// clear out the entries for the next round
tvm.passage.clear();
}
}
}
}
I'm trying to read appointments from Outlook calendar using ExchangeServiceBinding but my solution takes appointments only from "default" outlook calendar and don't read from "sub calendars/custom calendars". Do you know how to define rest of the calendars or do you know better solution which contains all calendars?
Critical part is that solution shouldn't contain MAPI because of next use in web service.
My current code:
private static List<List<string>> ReadCalendarEvents(string email)
{
List<List<string>> calendarEvents = new List<List<string>>();
// Specify the request version.
esb.RequestServerVersionValue = new RequestServerVersion();
esb.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2007;
// Form the FindItem request.
FindItemType findItemRequest = new FindItemType();
CalendarViewType calendarView = new CalendarViewType();
calendarView.StartDate = DateTime.Now.AddDays(-7);
calendarView.EndDate = DateTime.Now.AddDays(200);
calendarView.MaxEntriesReturned = 1000;
calendarView.MaxEntriesReturnedSpecified = true;
findItemRequest.Item = calendarView;
// Define which item properties are returned in the response.
ItemResponseShapeType itemProperties = new ItemResponseShapeType();
// Use the Default shape for the response.
//itemProperties.BaseShape = DefaultShapeNamesType.IdOnly;
itemProperties.BaseShape = DefaultShapeNamesType.AllProperties;
findItemRequest.ItemShape = itemProperties;
DistinguishedFolderIdType[] folderIDArray = new DistinguishedFolderIdType[1];
folderIDArray[0] = new DistinguishedFolderIdType();
folderIDArray[0].Id = DistinguishedFolderIdNameType.calendar;
//
folderIDArray[0].Mailbox = new EmailAddressType();
folderIDArray[0].Mailbox.EmailAddress = email;
findItemRequest.ParentFolderIds = folderIDArray;
// Define the traversal type.
findItemRequest.Traversal = ItemQueryTraversalType.Shallow;
try
{
// Send the FindItem request and get the response.
FindItemResponseType findItemResponse = esb.FindItem(findItemRequest);
// Access the response message.
ArrayOfResponseMessagesType responseMessages = findItemResponse.ResponseMessages;
ResponseMessageType[] rmta = responseMessages.Items;
int folderNumber = 0;
foreach (ResponseMessageType rmt in rmta)
{
// One FindItemResponseMessageType per folder searched.
FindItemResponseMessageType firmt = rmt as FindItemResponseMessageType;
if (firmt.RootFolder == null)
continue;
FindItemParentType fipt = firmt.RootFolder;
object obj = fipt.Item;
// FindItem contains an array of items.
if (obj is ArrayOfRealItemsType)
{
ArrayOfRealItemsType items =
(obj as ArrayOfRealItemsType);
if (items.Items == null)
{
folderNumber++;
}
else
{
foreach (ItemType it in items.Items)
{
if (it is CalendarItemType)
{
CalendarItemType cal = (CalendarItemType)it;
List<string> ce = new List<string>();
ce.Add(cal.Location);
ce.Add(cal.Start.ToShortDateString() + " " + cal.Start.ToShortTimeString());
ce.Add(cal.End.ToShortDateString() + " " + cal.End.ToShortTimeString());
ce.Add(cal.Subject);
if (cal.Organizer != null)
{
ce.Add(cal.Organizer.Item.Name);
}
calendarEvents.Add(ce);
Console.WriteLine(cal.Subject + " " + cal.Start.ToShortDateString() + " " + cal.Start.ToShortTimeString() + " " + cal.Location);
}
}
folderNumber++;
}
}
}
}
catch (Exception e)
{
throw;
}
finally
{
}
return calendarEvents;
}
In EWS you need to query one folder at a time, for non default folders you will first need to find the FolderId before you can then query the appointments (or items) within a Folder. To find all the Calendar folders in a Mailbox you need to use the FindFolder operation and create a restriction to limit the result to folder with a FolderClass of IPF.Appointment eg
// Create the request and specify the travesal type.
FindFolderType findFolderRequest = new FindFolderType();
findFolderRequest.Traversal = FolderQueryTraversalType.Deep;
// Define the properties that are returned in the response.
FolderResponseShapeType responseShape = new FolderResponseShapeType();
responseShape.BaseShape = DefaultShapeNamesType.Default;
findFolderRequest.FolderShape = responseShape;
// Identify which folders to search.
DistinguishedFolderIdType[] folderIDArray = new DistinguishedFolderIdType[1];
folderIDArray[0] = new DistinguishedFolderIdType();
folderIDArray[0].Id = DistinguishedFolderIdNameType.msgfolderroot;
IsEqualToType iet = new IsEqualToType();
PathToUnindexedFieldType FolderClass = new PathToUnindexedFieldType();
FolderClass.FieldURI = UnindexedFieldURIType.folderFolderClass;
iet.Item = FolderClass;
FieldURIOrConstantType constantType = new FieldURIOrConstantType();
ConstantValueType constantValueType = new ConstantValueType();
constantValueType.Value = "IPF.Appointment";
constantType.Item = constantValueType;
iet.FieldURIOrConstant = constantType;
// Add the folders to search to the request.
RestrictionType restriction = new RestrictionType();
restriction.Item = iet;
findFolderRequest.Restriction = restriction;
findFolderRequest.ParentFolderIds = folderIDArray;
try
{
// Send the request and get the response.
FindFolderResponseType findFolderResponse = esb.FindFolder(findFolderRequest);
// Get the response messages.
ResponseMessageType[] rmta = findFolderResponse.ResponseMessages.Items;
foreach (ResponseMessageType rmt in rmta)
{
// Cast to the correct response message type.
if (((FindFolderResponseMessageType)rmt).ResponseClass == ResponseClassType.Success) {
foreach (FolderType folder in ((FindFolderResponseMessageType)rmt).RootFolder.Folders) {
Console.WriteLine(folder.DisplayName);
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
You also might want to look at using the EWS Managed API which will save you greatly time and the amount of code you need to write
Cheers
Glen
we try to implement the nice local notifications extension of distriqt.
With the deactivate event new notifications were set:
notification.id = int(Math.random()*100);
notification.tickerText = _asde + " asdasd!";
notification.title = _asde + " asd!";
notification.body = "asd!";
notification.iconType = NotificationIconType.APPLICATION;
notification.count = 0;
notification.repeatInterval = 0;
notification.vibrate = false;
notification.playSound = true;
notification.soundName = "assets/sounds/notification.mp3";
notification.delay = secondsToDeath;
notification.data = "Some notification data to attach "+notification.id;
try
{
Notifications.service.notify( notification.id, notification );
_count ++;
Notifications.service.setBadgeNumber( _count );
}
catch (e:Error)
{
}
If the user clicks on the app and deactivates it again, new notifications were set.
The old notifications are still available and are displayed but we want the old to be deleted.
We haven't found a method to unregister the old notifications.
Any idea?
private static const DEACTIVATE_NOTIFICATION_ID_4 : int = 4;
Is declared.
if(_GoodA == true){
setSpielenFertigDate.time = 2400000*(1-_aktuellerFreudeWert/_maximalerFreudeWert);
var secondsToSpielenFertig:int = int((setSpielenFertigDate.time)/ 1000);
trace("halloe" + _fernseherAn.toString());
notification4.id = DEACTIVATE_NOTIFICATION_ID_4;
notification4.tickerText = "He test it!";
notification4.title = "sdf is happy!";
notification4.body = "sdf test is on!";
notification4.iconType = NotificationIconType.APPLICATION;
notification4.count = 0;
notification4.repeatInterval = 0;
notification4.vibrate = false;
notification4.playSound = true;
notification4.soundName = "assets/sounds/notification.mp3";
notification4.delay = secondsToSpielenFertig;
notification4.data = "Some notification data to attach "+ notification4.id;
try
{
Notifications.service.notify( notification4.id, notification4 );
_count ++;
Notifications.service.setBadgeNumber( _count );
}
catch (e:Error)
{
}
}
else{
trace("halloe2" + _fernseherAn.toString());
setSpielenDate.time = 5100000*(_aktuellerFreudeWert/_maximalerFreudeWert);
var secondsToSpielen:int = int((setSpielenDate.time)/ 1000);
notification4.id = DEACTIVATE_NOTIFICATION_ID_4;
notification4.tickerText = "He tested it!";
notification4.title = "sdf is unhappy!";
notification4.body = "sdf test is off!";
notification4.iconType = NotificationIconType.APPLICATION;
notification4.count = 0;
notification4.repeatInterval = 0;
notification4.vibrate = false;
notification4.playSound = true;
notification4.soundName = "assets/sounds/notification.mp3";
//Sekunden bis Nachricht geschickt wird
notification4.delay = secondsToSpielen;
notification4.data = "Some notification data to attach "+notification4.id;
try
{
Notifications.service.notify( notification4.id, notification4 );
_count ++;
Notifications.service.setBadgeNumber( _count );
}
catch (e:Error)
{
}
}
If the deactivate event of the app is fired it traces the correct part of the if and else clause. But it won't update the body and title...
There are two ways to do this with our extension. Both involve tracking the ID of the notification.
The first is to track your last notification and "cancel" it from the notification area. To do this you need to store at least the ID of the last created notification. The part of the code that you're probably interested in is the cancel function, this removes a notification from the notification panel by specifying the id of the notification to remove.
Somewhere in your class declare a reference to the last notification:
private var _lastNotification : Notification;
Then in your deactivate handler:
var notification:Notification = new Notification();
notification.id = int(Math.random()*100);
notification.tickerText = "Deactivated";
notification.title = "TEST";
notification.body = "Application Deactivated";
if (_lastNotification != null)
Notifications.service.cancel( _lastNotification.id );
Notifications.service.notify( notification.id, notification );
// Set this to be the recent notification displayed
_lastNotification = notification;
The second option is to use a single notification id for all of your deactivate notifications. In this case you choose a constant ID to use for your notification and update the notification as required. The notification manager will not show an additional notification but simply update the one with the specified ID (or show it if it has been closed by the user).
private static const DEACTIVATE_NOTIFICATION_ID : int = 10;
var notification:Notification = new Notification();
notification.id = DEACTIVATE_NOTIFICATION_ID;
notification.tickerText = "Deactivated";
notification.title = "TEST";
notification.body = "Application Deactivated";
Notifications.service.notify( notification.id, notification );
Hope this helps!