Есть люди, которые скажут вам, что Земля круглая (или, возможно, Земля - сплющенный сфероид, если они хотят использовать странные слова). Они лгут.
Есть люди, которые скажут вам, что регулярные выражения не должны быть рекурсивными. Они ограничивают вас. Они должны подчинить вас, и они делают это, удерживая вас в невежестве.
Вы можете жить в своей реальности или принимать красную таблетку.
Как лорд Маршал (он родственник из класса Marshal .NET?), я видел Underverse Stack Based Regex-Verse и возвращался с помощью знаний о силе, которые вы не можете себе представить. Да, я думаю, что один из них защищал их, но они смотрели футбол по телевизору, поэтому это было не сложно.
Я думаю, что XML-пример довольно прост. RegEx (в синтаксисе .NET), сдутый и закодированный в base64, чтобы облегчить понимание вашим слабым умом, должен быть примерно таким:
7L0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28
995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8itn6Po9/3eIue3+Px7/3F
86enJ8+/fHn64ujx7/t7vFuUd/Dx65fHJ6dHW9/7fd/t7fy+73Ye0v+f0v+Pv//JnTvureM3b169
OP7i9Ogyr5uiWt746u+BBqc/8dXx86PP7tzU9mfQ9tWrL18d3UGnW/z7nZ9htH/y9NXrsy9fvPjq
i5/46ss3p4z+x3e8b452f9/x93a2HxIkH44PpgeFyPD6lMAEHUdbcn8ffTP9fdTrz/8rBPCe05Iv
p9WsWF788Obl9MXJl0/PXnwONLozY747+t7x9k9l2z/4vv4kqo1//993+/vf2kC5HtwNcxXH4aOf
LRw2z9/v8WEz2LTZcpaV1TL/4c3h66ex2Xv95vjF0+PnX744PbrOm59ZVhso5UHYME/dfj768H7e
Yy5uQUydDAH9+/4eR11wHbqdfPnFF6cv3ogq/V23t++4z4620A13cSzd7O1s/77rpw+ePft916c7
O/jj2bNnT7e/t/397//M9+ibA/7s6ZNnz76PP0/kT2rz/Ts/s/0NArvziYxVEZWxbm93xsrUfnlm
rASN7Hf93u/97vvf+2Lx/e89L7+/FSXiz4Bkd/hF5mVq9Yik7fcncft9350QCu+efkr/P6BfntEv
z+iX9c4eBrFz7wEwpB9P+d9n9MfuM3yzt7Nzss0/nuJfbra3e4BvZFR7z07pj3s7O7uWJM8eCkme
nuCPp88MfW6kDeH7+26PSTX8vu+ePAAiO4LVp4zIPWC1t7O/8/+pMX3rzo2KhL7+8s23T1/RhP0e
vyvm8HbsdmPXYDVhtpdnAzJ1k1jeufOtUAM8ffP06Zcnb36fl6dPXh2f/F6nRvruyHfMd9rgJp0Y
gvsRx/6/ZUzfCtX4e5hTndGzp5jQo9e/z+s3p1/czAUMlts+P3tz+uo4tISd745uJxvb3/v4ZlWs
mrjfd9SG/swGPD/6+nh+9MF4brTBRmh1Tl5+9eT52ckt5oR0xldPzp7GR8pfuXf5PWJv4nJIwvbH
W3c+GY3vPvrs9zj8Xb/147/n7/b7/+52DD2gsSH8zGDvH9+i9/fu/PftTfTXYf5hB+9H7P1BeG52
MTtu4S2cTAjDizevv3ry+vSNb8N+3+/1po2anj4/hZsGt3TY4GmjYbEKDJ62/pHB+3/LmL62wdsU
1J18+eINzTJr3dMvXr75fX7m+MXvY9XxF2e/9+nTgPu2bgwh5U0f7u/74y9Pnh6/OX4PlA2UlwTn
xenJG8L996VhbP3++PCrV68QkrjveITxr2TIt+lL+f3k22fPn/6I6f/fMqZvqXN/K4Xps6sazUGZ
GeQlar49xEvajzI35VRevDl78/sc/b7f6jkG8Va/x52N4L9lBe/kZSh1hr9fPj19+ebbR4AifyuY
12efv5CgGh9TroR6Pj2l748iYxYgN8Z7pr0HzRLg66FnRvcjUft/45i+pRP08vTV6TOe2N/9jv37
R9P0/5YxbXQDeK5E9R12XdDA/4zop+/9Ht/65PtsDVlBBUqko986WsDoWqvbPD2gH/T01DAC1NVn
3/uZ0feZ+T77fd/GVMkA4KjeMcg6RcvQLRl8HyPaWVStdv17PwHV0bOB9xUh7rfMp5Zu3icBJp25
D6f0NhayHyfI3HXHY6YYCw7Pz17fEFhQKzS6ZWChrX+kUf7fMqavHViEPPKjCf1/y5hukcyPTvjP
mHQCppRDN4nbVFPaT8+ekpV5/TP8g/79mVPo77PT1/LL7/MzL7548+XvdfritflFY00fxIsvSQPS
mvctdYZpbt7vxKRfj3018OvC/hEf/79lTBvM3debWj+b8KO0wP+3OeM2aYHumuCAGonmCrxw9cVX
X1C2d4P+uSU7eoBUMzI3/f9udjbYl/el04dI7s8fan8dWRjm6gFx+NrKeFP+WX0CxBdPT58df/X8
DaWLX53+xFdnr06f/szv++NnX7x8fnb6NAhIwsbPkPS7iSUQAFETvP2Tx8+/Og0Xt/yBvDn9vd/c
etno8S+81QKXptq/ffzKZFZ+4e/743e8zxino+8RX37/k595h5/H28+y7fPv490hQdJ349E+txB3
zPZ5J/jsR8bs/y1j2hh/2fkayOqEmYcej0cXUWMN7QrqBwjDrVZRfyQM3xjj/EgYvo4wfLTZrnVS
ebdKq0XSZJvzajKQDUv1/P3NwbEP7cN5+Odivv9/ysPfhHfkOP6b9Fl+91v7LD9aCvp/+Zi+7lLQ
j0zwNzYFP+/Y6r1NcFeDbfBIo8rug3zS3/3WPumPlN3/y8f0I2X3cz4FP+/Y6htSdr2I42fEuSPX
/ewpL4e9/n1evzn94hb+Plpw2+dnbyh79zx0CsPvbq0lb+UQ/h7xvqPq/Gc24PnR18fzVrp8I57d
mehj7ebk5VdPnp+d3GJOSP189eTsaXyk/JV7l98j4SAZgRxtf7x155PR+O6jz36Pw9/1Wz/+e/5u
v//vbsfQAxobws8M9v7xLXp/785/395ED4nO1wx5fsTeH4LnRva+eYY8rpZUBFb/j/jfm8XAvfEj
4/b/ljF1F9B/jx5PhAkp1nu/+y3n+kdZp/93jWmjJ/M11TG++VEG6puZn593PPejoOyHMQU/79jq
GwrKfpSB+tmcwZ93XPkjZffDmIKfd2z1DSm7bmCoPPmjBNT74XkrVf71I/Sf6wTU7XJA4RB+lIC6
mW1+xN5GWw1/683C5rnj/m364cmr45Pf6/SN9H4Us4LISn355vjN2ZcvtDGT6fHvapJcMISmxc0K
MAD4IyP6/5Yx/SwkP360FvD1VTH191mURr/HUY+2P3I9boPnz7Ju/pHrcWPnP3I9/r/L3sN0v52z
0fEgNrgbL8/Evfh9fw/q5Xf93u/97vvf+2Lx/e89L7+/Fe3iZ37f34P5h178kTfx/5YxfUs8vY26
7/d4/OWbb5++ogn7PX5XzOHtOP3GrsHmqobOVO/8Hh1Gk/TPl198QS6w+rLb23fcZ0fMaTfjsv29
7Zul7me2v0FgRoYVURnf9nZEkDD+H2VDf8hjeq8xff1s6GbButNLacEtefHm9VdPXp++CRTw7/v9
r6vW8b9eJ0+/PIHzs1HHdyKE/x9L4Y+s2f+PJPX/1dbsJn3wrY6wiqv85vjVm9Pnp+DgN8efM5va
j794+eb36Xz3mAf5+58+f3r68s230dRvJcxKn/l//oh3f+7H9K2O0r05PXf85s2rH83f/1vGdAvd
w+qBFqsoWvzspozD77EpXYeZ7yzdfxy0ec+l+8e/8FbR84+Wd78xbvn/qQQMz/J7L++GPB7N0MQa
2vTMBwjDrVI0PxKGb4xxfiQMX0cYPuq/Fbx2C1sU8yEF+F34iNsx1xOGa9t6l/yX70uqmxu+qBGm
AxlxWwVS11O97ULqlsFIUvUnT4/fHIuL//3f9/t9J39Y9m8W/Tuc296yUeX/b0PiHwUeP1801Y8C
j/9vz9+PAo8f+Vq35Jb/n0rAz7Kv9aPA40fC8P+RMf3sC8PP08DjR1L3DXHoj6SuIz/CCghZNZb8
fb/Hf/2+37tjvuBY9vu3jmRvxNeGgQAuaAF6Pwj8/+e66M8/7rwpRNj6uVwXZRl52k0n3FVl95Q+
+fz0KSu73/dtkGDYdvZgSP5uskadrtViRKyal2IKAiQfiW+FI+tET/9/Txj9SFf8SFf8rOuKzagx
+r/vD34mUADO1P4/AQAA//8=
Параметры для установки: RegexOptions.ExplicitCapture
, Группа захвата, которую вы ищете, - ELEMENTNAME
. Если группа захвата ERROR
не пуста, тогда произошла ошибка синтаксического анализа, и регекс остановился.
Если у вас есть проблемы с переустановкой его на понятное для пользователя регулярное выражение, это должно помочь:
static string FromBase64(string str)
{
byte[] byteArray = Convert.FromBase64String(str);
using (var msIn = new MemoryStream(byteArray))
using (var msOut = new MemoryStream()) {
using (var ds = new DeflateStream(msIn, CompressionMode.Decompress)) {
ds.CopyTo(msOut);
}
return Encoding.UTF8.GetString(msOut.ToArray());
}
}
Если вы не уверены, нет, я НЕ шучу (но, возможно, я лгу). Это будет работать. Я собрал тонны тестов для тестирования, и я даже использовал (часть) тесты соответствия . Это токенизатор, а не полноразмерный парсер, поэтому он будет разделять только XML на его компонентные маркеры. Он не будет анализировать / интегрировать DTD.
Ох ... если вы хотите исходный код регулярного выражения с некоторыми вспомогательными методами:
Вы не можете использовать Firebase Admin SDK в приложении для Android вместе с клиентскими библиотеками Firebase Android. SDK обе предоставляют классы с тем же самым пакетом и именем класса, поэтому он не сможет использовать их одновременно (как компилятор узнает, какой из них вы собираетесь встраивать в ваше приложение?).
В качестве примера рассмотрим javadoc для FirebaseOptions Builder в клиентской библиотеке Android:
com.google.firebase.FirebaseOptions.Builder
Теперь посмотрите на тот же класс из java Admin SDK (обратите внимание, что URL-адрес отличается):
com.google.firebase.FirebaseOptions.Builder
Вы сами можете убедиться, что это разные вещи, хотя у них одно и то же имя. Поэтому ваш компилятор смотрит на определение SDK Android, а не на определение SDK администратора.
Как сказал Фрэнк, вы, вероятно, не хотите использовать библиотеку Admin в своем приложении для Android. Если вы хотите использовать SDK администратора, используйте его с сервера, которым вы управляете, и при необходимости сообщите об этом Android-приложению.
Теперь класс FirebaseOptions, взятый из других зависимостей, можно удалить компоненты firebase из других зависимостей, как показано ниже, используя тег exclude.
compile 'com.google.firebase:firebase-admin:5.8.0'
compile ('com.google.firebase:firebase-messaging:9.6.1'){
exclude module: 'firebase-common'
}
compile ('com.google.firebase:firebase-auth:9.6.1'){
exclude module: 'firebase-common'
}
compile ('com.google.firebase:firebase-database:9.6.1'){
exclude module: 'firebase-common'
}
compile ('com.firebase:firebase-client-android:2.5.0'){
exclude module: 'firebase-common'
}
Как утверждает принятый ответ, не стоит добавлять Firebase Admin в ваше приложение для Android, которое использует Firebase, потому что есть классы с одинаковыми именами.
Я хотел создать пользовательский токен ( https://firebase.google.com/docs/auth/android/custom-auth ), поэтому я закончил работу:
1) Создайте отдельный сервер без интерфейса.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
finish() // Just end the app here.
}
}
<resources>
<style name="AppTheme" parent="@android:style/Theme.NoDisplay">
</style>
</resources>
2) Добавьте IntentService к серверному приложению и создайте пользовательский токен.
class CustomTokenService : IntentService(CustomTokenService::class.java.simpleName) {
// Runs in its own thread.
override fun onHandleIntent(intent: Intent?) {
// Initialize FirebaseApp only when not already initialized.
try {
FirebaseApp.getInstance()
} catch (ex: IllegalStateException) {
try {
val inputStream = assets.open("serviceAccountKey.json")
val options = FirebaseOptions.Builder().
setCredential(FirebaseCredentials.fromCertificate(inputStream)).
setDatabaseUrl("https://YOUR_APP.firebaseio.com/").
build()
FirebaseApp.initializeApp(options)
inputStream.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
// In real life, you should verify ID/PW before creating custom token.
val id = intent!!.getStringExtra("ID")
val pw = intent.getStringExtra("PW")
val additionalClaims = HashMap<String, Any>()
additionalClaims.put("premiumAccount", true)
FirebaseAuth.getInstance().createCustomToken(id, additionalClaims).
addOnSuccessListener { customToken ->
// Send custom token back to client.
val resultReceiver = intent.getParcelableExtra<ResultReceiver>(RESULT_RECEIVER)
val bundle = Bundle()
bundle.putString(CUSTOM_TOKEN, customToken)
resultReceiver.send(Activity.RESULT_OK, bundle)
}
}
}
Обратите внимание, что я отправляю пользовательский токен обратно клиенту через «ResultReceiver», но вы можете использовать другие способы, такие как «Messenger» или «BroadcastReceiver».
3) От клиента я запускаю службу, которая находится в серверном приложении.
String MYSERVER = "SERVER_ID"; // e.g. "com.domain.myserver"
String CUSTOM_TOKEN_SERVICE = MYSERVER + ".CustomTokenService";
Intent intent = new Intent();
intent.putExtra("ID", ID);
intent.putExtra("PW", PW);
intent.putExtra(RESULT_RECEIVER, mResultReceiver);
intent.setComponent(new ComponentName(MYSERVER, CUSTOM_TOKEN_SERVICE));
getContext().startService(intent);
4) Когда я получаю пользовательский токен из приложения-сервера, я вхожу в Firebase.
ResultReceiver resultReceiver = new ResultReceiver(new Handler()) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
String customToken = resultData.getString(CUSTOM_TOKEN);
mFirebaseAuth.signInWithCustomToken(customToken);
}
};
Parcel parcel = Parcel.obtain();
resultReceiver.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
mResultReceiver = ResultReceiver.CREATOR.createFromParcel(parcel);
parcel.recycle();
5) И файлы конфигурации Gradle.
buildscript {
ext.kotlin_version = '1.2.21'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
---------------------------------------------------------------------------
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 26
defaultConfig {
applicationId "org.solamour.myserver"
minSdkVersion 14
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
javaCompileOptions {
annotationProcessorOptions {
includeCompileClasspath false
}
}
resConfigs "auto"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// Conflict with dependency 'com.google.code.findbugs:jsr305' in project ':app'.
// Resolved versions for app (1.3.9) and test app (2.0.1) differ.
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:2.0.1' // Or "1.3.9".
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation 'com.google.firebase:firebase-admin:4.1.6'
implementation 'com.android.support:multidex:1.0.2'
}
Самая высокая версия Firebase Admin, которую я смог использовать, была «4.1.6»; что-то после этого включало много изменений в файл градиента (и это тоже не закончилось).