Advertisement
Guest User

Untitled

a guest
Nov 17th, 2017
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* HebSupport - Hebrew support for iPhone
  2.  * Copyright (C) 2009 Aviram Segal (planB) Liraz Elias (Liraz) and Omri Gilad (mmgm)
  3. */
  4.  
  5. /*
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful, but
  12.  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  13.  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14.  * for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License along
  17.  * with this program; if not, write to the Free Software Foundation, Inc.,
  18.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19.  */
  20.  
  21. #import <Foundation/Foundation.h>
  22. #import "RegexKitLite.h"
  23. #include "substrate.h"
  24. #include "iVrit.h"
  25. #include <alloca.h>
  26. #include <unistd.h>
  27. #include "ABMemberCell.h"
  28. #include <execinfo.h>
  29.  
  30. /* Declare ICU functions */
  31. extern "C" void* ubidi_open();
  32. extern "C" void ubidi_close(void*);
  33. extern "C" void ubidi_setPara( void*, UChar*, int, UBiDiLevel, void*, UErrorCode* );
  34. extern "C" int32_t ubidi_writeReordered( void*, UChar*, int, uint16_t, UErrorCode* );
  35. extern "C" void ubidi_setReorderingMode(void*, UBiDiReorderingMode);
  36. extern "C" UBiDiDirection ubidi_getDirection(void*);
  37. extern "C" UBiDiLevel ubidi_getLevelAt(void*, int32_t);
  38. extern "C" UBiDiLevel ubidi_getParaLevel(void*);
  39. extern "C" UBool u_isalpha (UChar);
  40.  
  41. #define WEBCORE_FRAMEWORK "/System/Library/PrivateFrameworks/WebCore.framework/WebCore"
  42. #define LIBICUCORE "/usr/lib/libicucore.dylib"
  43.  
  44. /* Bidi */
  45. FloatSize (*__orig__Font$drawText)(void* _this, void* context, TextRun& run, FloatPoint& point, int from, int to) = 0x0;
  46.  
  47. FloatSize __Font$drawText(void* _this, void* context, TextRun& run, FloatPoint& point, int from, int to) {
  48.     void *bidi;
  49.     UErrorCode err = U_ZERO_ERROR;
  50.     UBiDiLevel level = UBIDI_DEFAULT_LTR;
  51.  
  52.     bidi=ubidi_open();
  53.  
  54.     ubidi_setReorderingMode(bidi, UBIDI_REORDER_NUMBERS_SPECIAL);
  55.  
  56.     UChar* input = (UChar*)run.m_characters;
  57.     int len = run.m_len;
  58.     ubidi_setPara( bidi, input, len, level, NULL, &err );
  59.     TextRun newRun = run;
  60.     UChar* output = (UChar*)alloca(len * sizeof(UChar));
  61.     UBiDiDirection dir;
  62.    
  63.     //NSLog(@"Inside hooked Font$drawText, len=%d", len);
  64.    
  65.     dir = ubidi_getDirection(bidi);
  66.    
  67.     if(dir == UBIDI_MIXED){
  68.         level = ubidi_getParaLevel(bidi);
  69.         if(level % 2 == 0){
  70.             ubidi_writeReordered( bidi, output, len, UBIDI_DO_MIRRORING, &err );
  71.             newRun.m_characters = output;
  72.         } else {
  73.             ubidi_writeReordered( bidi, output, len, UBIDI_OUTPUT_REVERSE, &err );
  74.             newRun.m_characters = output;
  75.             newRun.m_rtl = true;
  76.         }
  77.     } else if(!(run.m_rtl) && (dir == UBIDI_RTL)){
  78.         ubidi_writeReordered( bidi, output, len, UBIDI_OUTPUT_REVERSE, &err );
  79.         newRun.m_characters = output;
  80.         newRun.m_rtl = true;
  81.     }
  82.  
  83.     FloatSize ret =  __orig__Font$drawText(_this, context, newRun, point, from, to);
  84.     ubidi_close(bidi);
  85.     return ret;
  86. }
  87.  
  88. static id ABMembersController$sectionIndexTitlesForTableView(id self, SEL sel, id tableView) {
  89.     NSInteger numOfSections = [self numberOfSectionsInTableView:tableView];
  90.     NSMutableArray* mutableTitles = [NSMutableArray arrayWithCapacity:(numOfSections+1)];
  91.     [mutableTitles insertObject:@"{search}" atIndex:0];
  92.     NSUInteger i;
  93.     for (i = 0; i < numOfSections; i++) {
  94.         NSObject* obj = [self tableView:tableView titleForHeaderInSection:i];
  95.         if(obj != nil) {
  96.                 [mutableTitles insertObject:obj atIndex:(i+1)];
  97.         }
  98.     }
  99.     return mutableTitles;
  100. }
  101.  
  102. static void ABMemberCell$drawContentInRectSelected(id self, SEL sel, CGRect rect, BOOL selected) {
  103.     ABMemberCell* _self = (ABMemberCell*)self;
  104.     NSArray* origNamePieces = _self->_namePieces;
  105.     // If empty array we can stop
  106.     if([origNamePieces count] == 0) {
  107.         [self orig$drawContentInRect:rect selected:selected];
  108.         return;
  109.     }
  110.    
  111.     NSMutableArray* namePieces = [NSMutableArray arrayWithArray:origNamePieces];
  112.     BOOL isHebrew = false;
  113.     int origHighlightIndex = _self->_highlightIndex;
  114.    
  115.     NSString* firstName = [namePieces objectAtIndex:0];
  116.     unichar firstNameFirstChar = [firstName characterAtIndex:0];
  117.     if(0x0590 <= firstNameFirstChar && firstNameFirstChar <= 0x05FF) {
  118.         isHebrew = true;
  119.     }
  120.    
  121.     if(isHebrew) {
  122.         int count = [namePieces count];
  123.         if(count == 2) {
  124.             [namePieces exchangeObjectAtIndex:0 withObjectAtIndex:1];
  125.             _self->_highlightIndex = (origHighlightIndex+1)%2;
  126.         } else if(count ==3) {
  127.             // Person with prefix such as Doctor
  128.             [namePieces exchangeObjectAtIndex:0 withObjectAtIndex:2];
  129.             if(_self->_highlightIndex != 1) {
  130.                 _self->_highlightIndex = (origHighlightIndex+2)%4;
  131.             }
  132.         }
  133.         _self->_namePieces = namePieces;
  134.     }
  135.     [self orig$drawContentInRect:rect selected:selected];
  136.     _self->_highlightIndex = origHighlightIndex;
  137.     _self->_namePieces = origNamePieces;
  138. }
  139.  
  140. void dumpSubviews(UIView *view, int level){
  141.     NSMutableString *padding = [[NSMutableString alloc] init];
  142.     for(int i=0; i<level; i++){
  143.         [padding appendString:@"\t"];
  144.     }
  145.     NSLog(@"%@%@", padding, [view class]);
  146.     [padding dealloc];
  147.     NSArray *subviews = [view subviews];
  148.     NSInteger count;
  149.     if((count = [subviews count]) == 0){
  150.         return;
  151.     } else {
  152.         level++;
  153.         for(int i=0; i<count; i++){
  154.             dumpSubviews([subviews objectAtIndex:i], level);
  155.         }
  156.         return;
  157.     }
  158. }
  159.  
  160. void setText(id self, SEL sel, NSString *text){
  161.     void *bidi;
  162.     UErrorCode err = U_ZERO_ERROR;
  163.     UBiDiLevel level = UBIDI_DEFAULT_LTR;
  164.     UBiDiDirection dir;
  165.    
  166.     /*if([text compare:@"dumpit"] == 0){
  167.         dumpSubviews([[UIApplication sharedApplication] keyWindow], 0);
  168.         return;
  169.     }*/
  170.    
  171.     int len = [text length];
  172.     bidi=ubidi_open();
  173.     UChar *input = (UChar *)calloc(len, sizeof(UChar));
  174.     [text getCharacters:(unichar *)input];
  175.     ubidi_setPara( bidi, (UChar*)input, len, level, NULL, &err );
  176.     dir = ubidi_getDirection(bidi);
  177.     Class cls = object_getClass(self);
  178.     //NSLog(@"Inside hooked [%@ setText:], text=%@, dir=%s", cls, text, dir==UBIDI_LTR?"LTR":"RTL/Mixed");
  179.     if(dir == UBIDI_RTL){
  180.         [self setTextAlignment:UITextAlignmentRight];
  181.     } else if (dir == UBIDI_MIXED) {
  182.         level = ubidi_getParaLevel(bidi);
  183.         if(level % 2 == 1) {
  184.             [self setTextAlignment:UITextAlignmentRight];
  185.         }
  186.         else {
  187.             [self setTextAlignment:UITextAlignmentLeft];
  188.         }
  189.     }
  190.     else {
  191.         [self setTextAlignment:UITextAlignmentLeft];
  192.     }
  193.     [self orig$setText:text];
  194.     ubidi_close(bidi);
  195.     free(input);
  196. }
  197.  
  198. void setTextAlignment(id self, SEL selector, UITextAlignment align) {
  199.     Class cls = [self class];
  200.     //NSLog(@"Inside hooked [%@ setTextAlignment:]", cls);
  201.     [self orig$setTextAlignment:align];
  202.     Ivar var = class_getInstanceVariable(cls, "_style");
  203.     NSString *string = [self _style];
  204.     if(string == nil){
  205.         //NSLog(@"Failed to load style, aborting direction mods");
  206.         return;
  207.     }
  208.     NSMutableString *newStyle = [[NSMutableString alloc] initWithString:string];
  209.     [string release];
  210.     NSString *newDir = [[NSString alloc] initWithFormat:@"%s", align==UITextAlignmentLeft?"ltr":"rtl"];
  211.     //TODO: Perform this without regex. I know its a waste of cycles on a device like the iPhone, but I <3 regex too much.
  212.     if([newStyle replaceOccurrencesOfRegex:@"direction\: (.){3}" withString:[NSString stringWithFormat:@"direction: %@", newDir]] == 0){
  213.         [newStyle appendFormat:@"direction: %@;", newDir];
  214.     }
  215.     [newDir dealloc];
  216.     object_setIvar(self, var, newStyle);
  217. }
  218.  
  219. NSString *styleString(id self, SEL selector){
  220.     UITextAlignment align = [self textAlignment];
  221.     NSString *newDir = [[NSString alloc] initWithFormat:@"%s", align==UITextAlignmentLeft?"ltr":"rtl"];
  222.     NSString *newAlign = [[NSString alloc] initWithFormat:@"%s", align==UITextAlignmentLeft?"left":"right"];
  223.     NSMutableString *newStyle = [NSMutableString stringWithString:[self orig$styleString]];
  224.     NSLog(@"Original style: %@", newStyle);
  225.     if([newStyle replaceOccurrencesOfRegex:@"text\-align\: (.){4,5};" withString:[NSString stringWithFormat:@"text-align: %@;", newAlign]] == 0){
  226.         [newStyle appendFormat:@"text-align: %@;", newAlign];
  227.     }
  228.     if([newStyle replaceOccurrencesOfRegex:@"direction\: (.){3}" withString:[NSString stringWithFormat:@"direction: %@", newDir]] == 0){
  229.         [newStyle appendFormat:@"direction: %@;", newDir];
  230.     }
  231.     [newDir dealloc];
  232.     [newAlign dealloc];
  233.     NSLog(@"Returning style: %@", newStyle);
  234.     return newStyle;
  235. }
  236.  
  237. void setContentToHTMLString(id self, SEL selector, NSString *html){
  238.     NSMutableString *text = [[NSMutableString alloc] initWithString:html];
  239.     [text replaceOccurrencesOfRegex:@"<(\/)?div>" withString:@""];
  240.    
  241.     void *bidi;
  242.     UErrorCode err = U_ZERO_ERROR;
  243.     UBiDiLevel level = UBIDI_DEFAULT_LTR;
  244.     UBiDiDirection dir;
  245.    
  246.     int len = [text length];
  247.     bidi=ubidi_open();
  248.     UChar *input = (UChar *)calloc(len, sizeof(UChar));
  249.     [text getCharacters:(unichar *)input];
  250.     ubidi_setPara( bidi, (UChar*)input, len, level, NULL, &err );
  251.     dir = ubidi_getDirection(bidi);
  252.     static UITextAlignment align;
  253.     if(dir == UBIDI_RTL){
  254.         align = UITextAlignmentRight;
  255.     } else if (dir == UBIDI_MIXED) {
  256.         level = ubidi_getParaLevel(bidi);
  257.         if(level % 2 == 1) {
  258.             align = UITextAlignmentRight;
  259.         }
  260.         else {
  261.             align = UITextAlignmentLeft;
  262.         }
  263.     }
  264.     else {
  265.         align = UITextAlignmentLeft;
  266.     }
  267.     [self setTextAlignment:align];
  268.     ubidi_close(bidi);
  269.     free(input);
  270.     [text release];
  271.     [self orig$setContentToHTMLString:html];
  272. }
  273.  
  274. extern "C" void HSInitialize() {
  275.     //freopen([@"/tmp/ivrit_log.txt" fileSystemRepresentation], "a", stderr);
  276.  
  277.     /* BiDi supprt  */
  278.     struct nlist nl[4];
  279.     int res = 0;
  280.     memset(nl, 0x0, sizeof(nl));
  281.     /* Hooks to WebCore/platform/graphics/Font.h - Font::drawText(GraphicsContext*, TextRun&, FloatPoint&, int from, int to); */
  282.     nl[0].n_un.n_name = (char *) "__ZNK7WebCore4Font8drawTextEPNS_15GraphicsContextERKNS_7TextRunERKNS_10FloatPointEii";
  283.     if((res = nlist(WEBCORE_FRAMEWORK, nl)) != -1) {
  284.         MSHookFunction((void *)nl[0].n_value, (void *)&__Font$drawText, (void **)&__orig__Font$drawText);
  285.         NSLog(@"Finished hooking funcs, res=%d", res);
  286.     } else {
  287.         NSLog(@"Failed to hook drawText, res=%d", res);
  288.     }
  289.  
  290.     // We need this lib for Bidi
  291.     if (dlopen(LIBICUCORE, RTLD_LAZY) == NULL) {
  292.         NSLog(@"Failed to load icu");
  293.     }
  294.     MSHookMessage(objc_getClass("ABMembersController"), @selector(sectionIndexTitlesForTableView:), &ABMembersController$sectionIndexTitlesForTableView, "orig$");
  295.    
  296.     MSHookMessage(objc_getClass("UITextField"), @selector(setText:), &setText, "orig$");
  297.     MSHookMessage(objc_getClass("UITextViewLegacy"), @selector(setText:), &setText, "orig$");
  298.     MSHookMessage(objc_getClass("UILabel"), @selector(setText:), &setText, "orig$");
  299.     MSHookMessage(objc_getClass("UITableViewCell"), @selector(setText:), &setText, "orig$");
  300.    
  301.     MSHookMessage(objc_getClass("UITextField"), @selector(setTextAlignment:), &setTextAlignment, "orig$");
  302.    
  303.     MSHookMessage(objc_getClass("UITextViewLegacy"), @selector(setContentToHTMLString:), &setContentToHTMLString, "orig$");
  304.     MSHookMessage(objc_getClass("UITextViewLegacy"), @selector(styleString), &styleString, "orig$");
  305.    
  306.     /*Class cls = objc_getClass("UITextViewLegacy");
  307.     unsigned int methodCount, i;
  308.     Method * methods = class_copyMethodList(cls, &methodCount);
  309.     for(i=0;i<methodCount;i++){
  310.         char *methodType = method_copyReturnType(methods[i]);
  311.         const char *methodName = sel_getName(method_getName(methods[i]));
  312.         NSLog(@"%s %s", methodType, methodName);
  313.         free(methodType);
  314.     }*/
  315.    
  316.     /*Class cls = objc_getClass("UITextViewLegacy");
  317.     unsigned int ivarCount, i;
  318.     Ivar * ivars = class_copyIvarList(cls, &ivarCount);
  319.     for(i=0;i<ivarCount;i++){
  320.         NSLog(@"%s %s", ivar_getTypeEncoding(ivars[i]), ivar_getName(ivars[i]));
  321.     }*/
  322.    
  323.     //Instead of ABModelRecord to support Cyntact in search
  324.     MSHookMessage(objc_getClass("ABMemberCell"), @selector(drawContentInRect:selected:), &ABMemberCell$drawContentInRectSelected, "orig$");
  325.     // Wait for saurik
  326.     //MSHookMessage(objc_getClass("ABMemberCell"), @selector(initWithSize:member:), &ABMemberCell$initWithSizeMember, "orig$");
  327.     /***************************************************************************************************************************/
  328. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement